]> xenbits.xensource.com Git - people/aperard/qemu-dm.git/commitdiff
target/i386: move x86 instruction emulator out of hvf
authorWei Liu <liuwe@linux.microsoft.com>
Fri, 7 Mar 2025 19:55:24 +0000 (11:55 -0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 17 Apr 2025 16:23:26 +0000 (18:23 +0200)
Move x86_decode, x86_emu, x86_flags and some headers to the new location.
Fix up all the inclusion sites in hvf.

Signed-off-by: Wei Liu <liuwe@linux.microsoft.com>
Link: https://lore.kernel.org/r/1741377325-28175-14-git-send-email-liuwe@linux.microsoft.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
24 files changed:
target/i386/emulate/meson.build
target/i386/emulate/x86.h [new file with mode: 0644]
target/i386/emulate/x86_decode.c [new file with mode: 0644]
target/i386/emulate/x86_decode.h [new file with mode: 0644]
target/i386/emulate/x86_emu.c [new file with mode: 0644]
target/i386/emulate/x86_emu.h [new file with mode: 0644]
target/i386/emulate/x86_flags.c [new file with mode: 0644]
target/i386/emulate/x86_flags.h [new file with mode: 0644]
target/i386/hvf/hvf.c
target/i386/hvf/meson.build
target/i386/hvf/vmx.h
target/i386/hvf/x86.c
target/i386/hvf/x86.h [deleted file]
target/i386/hvf/x86_cpuid.c
target/i386/hvf/x86_decode.c [deleted file]
target/i386/hvf/x86_decode.h [deleted file]
target/i386/hvf/x86_descr.h
target/i386/hvf/x86_emu.c [deleted file]
target/i386/hvf/x86_emu.h [deleted file]
target/i386/hvf/x86_flags.c [deleted file]
target/i386/hvf/x86_flags.h [deleted file]
target/i386/hvf/x86_mmu.c
target/i386/hvf/x86_task.c
target/i386/hvf/x86hvf.c

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4edd4f462fc742ba099707f556f9cb06e5fcf09d 100644 (file)
@@ -0,0 +1,5 @@
+i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files(
+  'x86_decode.c',
+  'x86_emu.c',
+  'x86_flags.c',
+))
diff --git a/target/i386/emulate/x86.h b/target/i386/emulate/x86.h
new file mode 100644 (file)
index 0000000..73edccf
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2016 Veertu Inc,
+ * Copyright (C) 2017 Veertu Inc,
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef X86_EMU_DEFS_H
+#define X86_EMU_DEFS_H
+
+typedef struct x86_register {
+    union {
+        struct {
+            uint64_t rrx;               /* full 64 bit */
+        };
+        struct {
+            uint32_t erx;               /* low 32 bit part */
+            uint32_t hi32_unused1;
+        };
+        struct {
+            uint16_t rx;                /* low 16 bit part */
+            uint16_t hi16_unused1;
+            uint32_t hi32_unused2;
+        };
+        struct {
+            uint8_t lx;                 /* low 8 bit part */
+            uint8_t hx;                 /* high 8 bit */
+            uint16_t hi16_unused2;
+            uint32_t hi32_unused3;
+        };
+    };
+} __attribute__ ((__packed__)) x86_register;
+
+/* 16 bit Task State Segment */
+typedef struct x86_tss_segment16 {
+    uint16_t link;
+    uint16_t sp0;
+    uint16_t ss0;
+    uint32_t sp1;
+    uint16_t ss1;
+    uint32_t sp2;
+    uint16_t ss2;
+    uint16_t ip;
+    uint16_t flags;
+    uint16_t ax;
+    uint16_t cx;
+    uint16_t dx;
+    uint16_t bx;
+    uint16_t sp;
+    uint16_t bp;
+    uint16_t si;
+    uint16_t di;
+    uint16_t es;
+    uint16_t cs;
+    uint16_t ss;
+    uint16_t ds;
+    uint16_t ldtr;
+} __attribute__((packed)) x86_tss_segment16;
+
+/* 32 bit Task State Segment */
+typedef struct x86_tss_segment32 {
+    uint32_t prev_tss;
+    uint32_t esp0;
+    uint32_t ss0;
+    uint32_t esp1;
+    uint32_t ss1;
+    uint32_t esp2;
+    uint32_t ss2;
+    uint32_t cr3;
+    uint32_t eip;
+    uint32_t eflags;
+    uint32_t eax;
+    uint32_t ecx;
+    uint32_t edx;
+    uint32_t ebx;
+    uint32_t esp;
+    uint32_t ebp;
+    uint32_t esi;
+    uint32_t edi;
+    uint32_t es;
+    uint32_t cs;
+    uint32_t ss;
+    uint32_t ds;
+    uint32_t fs;
+    uint32_t gs;
+    uint32_t ldt;
+    uint16_t trap;
+    uint16_t iomap_base;
+} __attribute__ ((__packed__)) x86_tss_segment32;
+
+/* 64 bit Task State Segment */
+typedef struct x86_tss_segment64 {
+    uint32_t unused;
+    uint64_t rsp0;
+    uint64_t rsp1;
+    uint64_t rsp2;
+    uint64_t unused1;
+    uint64_t ist1;
+    uint64_t ist2;
+    uint64_t ist3;
+    uint64_t ist4;
+    uint64_t ist5;
+    uint64_t ist6;
+    uint64_t ist7;
+    uint64_t unused2;
+    uint16_t unused3;
+    uint16_t iomap_base;
+} __attribute__ ((__packed__)) x86_tss_segment64;
+
+/* segment descriptors */
+typedef struct x86_segment_descriptor {
+    uint64_t    limit0:16;
+    uint64_t    base0:16;
+    uint64_t    base1:8;
+    uint64_t    type:4;
+    uint64_t    s:1;
+    uint64_t    dpl:2;
+    uint64_t    p:1;
+    uint64_t    limit1:4;
+    uint64_t    avl:1;
+    uint64_t    l:1;
+    uint64_t    db:1;
+    uint64_t    g:1;
+    uint64_t    base2:8;
+} __attribute__ ((__packed__)) x86_segment_descriptor;
+
+static inline uint32_t x86_segment_base(x86_segment_descriptor *desc)
+{
+    return (uint32_t)((desc->base2 << 24) | (desc->base1 << 16) | desc->base0);
+}
+
+static inline void x86_set_segment_base(x86_segment_descriptor *desc,
+                                        uint32_t base)
+{
+    desc->base2 = base >> 24;
+    desc->base1 = (base >> 16) & 0xff;
+    desc->base0 = base & 0xffff;
+}
+
+static inline uint32_t x86_segment_limit(x86_segment_descriptor *desc)
+{
+    uint32_t limit = (uint32_t)((desc->limit1 << 16) | desc->limit0);
+    if (desc->g) {
+        return (limit << 12) | 0xfff;
+    }
+    return limit;
+}
+
+static inline void x86_set_segment_limit(x86_segment_descriptor *desc,
+                                         uint32_t limit)
+{
+    desc->limit0 = limit & 0xffff;
+    desc->limit1 = limit >> 16;
+}
+
+typedef struct x86_call_gate {
+    uint64_t offset0:16;
+    uint64_t selector:16;
+    uint64_t param_count:4;
+    uint64_t reserved:3;
+    uint64_t type:4;
+    uint64_t dpl:1;
+    uint64_t p:1;
+    uint64_t offset1:16;
+} __attribute__ ((__packed__)) x86_call_gate;
+
+static inline uint32_t x86_call_gate_offset(x86_call_gate *gate)
+{
+    return (uint32_t)((gate->offset1 << 16) | gate->offset0);
+}
+
+#define GDT_SEL     0
+#define LDT_SEL     1
+
+typedef struct x86_segment_selector {
+    union {
+        uint16_t sel;
+        struct {
+            uint16_t rpl:2;
+            uint16_t ti:1;
+            uint16_t index:13;
+        };
+    };
+} __attribute__ ((__packed__)) x86_segment_selector;
+
+/* useful register access  macros */
+#define x86_reg(cpu, reg) ((x86_register *) &cpu->regs[reg])
+
+#define RRX(cpu, reg)   (x86_reg(cpu, reg)->rrx)
+#define RAX(cpu)        RRX(cpu, R_EAX)
+#define RCX(cpu)        RRX(cpu, R_ECX)
+#define RDX(cpu)        RRX(cpu, R_EDX)
+#define RBX(cpu)        RRX(cpu, R_EBX)
+#define RSP(cpu)        RRX(cpu, R_ESP)
+#define RBP(cpu)        RRX(cpu, R_EBP)
+#define RSI(cpu)        RRX(cpu, R_ESI)
+#define RDI(cpu)        RRX(cpu, R_EDI)
+#define R8(cpu)         RRX(cpu, R_R8)
+#define R9(cpu)         RRX(cpu, R_R9)
+#define R10(cpu)        RRX(cpu, R_R10)
+#define R11(cpu)        RRX(cpu, R_R11)
+#define R12(cpu)        RRX(cpu, R_R12)
+#define R13(cpu)        RRX(cpu, R_R13)
+#define R14(cpu)        RRX(cpu, R_R14)
+#define R15(cpu)        RRX(cpu, R_R15)
+
+#define ERX(cpu, reg)   (x86_reg(cpu, reg)->erx)
+#define EAX(cpu)        ERX(cpu, R_EAX)
+#define ECX(cpu)        ERX(cpu, R_ECX)
+#define EDX(cpu)        ERX(cpu, R_EDX)
+#define EBX(cpu)        ERX(cpu, R_EBX)
+#define ESP(cpu)        ERX(cpu, R_ESP)
+#define EBP(cpu)        ERX(cpu, R_EBP)
+#define ESI(cpu)        ERX(cpu, R_ESI)
+#define EDI(cpu)        ERX(cpu, R_EDI)
+
+#define RX(cpu, reg)   (x86_reg(cpu, reg)->rx)
+#define AX(cpu)        RX(cpu, R_EAX)
+#define CX(cpu)        RX(cpu, R_ECX)
+#define DX(cpu)        RX(cpu, R_EDX)
+#define BP(cpu)        RX(cpu, R_EBP)
+#define SP(cpu)        RX(cpu, R_ESP)
+#define BX(cpu)        RX(cpu, R_EBX)
+#define SI(cpu)        RX(cpu, R_ESI)
+#define DI(cpu)        RX(cpu, R_EDI)
+
+#define RL(cpu, reg)   (x86_reg(cpu, reg)->lx)
+#define AL(cpu)        RL(cpu, R_EAX)
+#define CL(cpu)        RL(cpu, R_ECX)
+#define DL(cpu)        RL(cpu, R_EDX)
+#define BL(cpu)        RL(cpu, R_EBX)
+
+#define RH(cpu, reg)   (x86_reg(cpu, reg)->hx)
+#define AH(cpu)        RH(cpu, R_EAX)
+#define CH(cpu)        RH(cpu, R_ECX)
+#define DH(cpu)        RH(cpu, R_EDX)
+#define BH(cpu)        RH(cpu, R_EBX)
+
+/* deal with GDT/LDT descriptors in memory */
+bool x86_read_segment_descriptor(CPUState *cpu,
+                                 struct x86_segment_descriptor *desc,
+                                 x86_segment_selector sel);
+bool x86_write_segment_descriptor(CPUState *cpu,
+                                  struct x86_segment_descriptor *desc,
+                                  x86_segment_selector sel);
+
+bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc,
+                        int gate);
+
+/* helpers */
+bool x86_is_protected(CPUState *cpu);
+bool x86_is_real(CPUState *cpu);
+bool x86_is_v8086(CPUState *cpu);
+bool x86_is_long_mode(CPUState *cpu);
+bool x86_is_long64_mode(CPUState *cpu);
+bool x86_is_paging_mode(CPUState *cpu);
+bool x86_is_pae_enabled(CPUState *cpu);
+
+enum X86Seg;
+target_ulong linear_addr(CPUState *cpu, target_ulong addr, enum X86Seg seg);
+target_ulong linear_addr_size(CPUState *cpu, target_ulong addr, int size,
+                              enum X86Seg seg);
+target_ulong linear_rip(CPUState *cpu, target_ulong rip);
+
+static inline uint64_t rdtscp(void)
+{
+    uint64_t tsc;
+    __asm__ __volatile__("rdtscp; "         /* serializing read of tsc */
+                         "shl $32,%%rdx; "  /* shift higher 32 bits stored in rdx up */
+                         "or %%rdx,%%rax"   /* and or onto rax */
+                         : "=a"(tsc)        /* output to tsc variable */
+                         :
+                         : "%rcx", "%rdx"); /* rcx and rdx are clobbered */
+
+    return tsc;
+}
+
+#endif
diff --git a/target/i386/emulate/x86_decode.c b/target/i386/emulate/x86_decode.c
new file mode 100644 (file)
index 0000000..ddd7b60
--- /dev/null
@@ -0,0 +1,2194 @@
+/*
+ * Copyright (C) 2016 Veertu Inc,
+ * Copyright (C) 2017 Google Inc,
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+
+#include "panic.h"
+#include "x86_decode.h"
+#include "x86_emu.h"
+
+#define OPCODE_ESCAPE   0xf
+
+static void decode_invalid(CPUX86State *env, struct x86_decode *decode)
+{
+    printf("%llx: failed to decode instruction ", env->eip);
+    for (int i = 0; i < decode->opcode_len; i++) {
+        printf("%x ", decode->opcode[i]);
+    }
+    printf("\n");
+    VM_PANIC("decoder failed\n");
+}
+
+uint64_t sign(uint64_t val, int size)
+{
+    switch (size) {
+    case 1:
+        val = (int8_t)val;
+        break;
+    case 2:
+        val = (int16_t)val;
+        break;
+    case 4:
+        val = (int32_t)val;
+        break;
+    case 8:
+        val = (int64_t)val;
+        break;
+    default:
+        VM_PANIC_EX("%s invalid size %d\n", __func__, size);
+        break;
+    }
+    return val;
+}
+
+static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode,
+                                    int size)
+{
+    uint64_t val = 0;
+
+    switch (size) {
+    case 1:
+    case 2:
+    case 4:
+    case 8:
+        break;
+    default:
+        VM_PANIC_EX("%s invalid size %d\n", __func__, size);
+        break;
+    }
+    target_ulong va  = linear_rip(env_cpu(env), env->eip) + decode->len;
+    emul_ops->read_mem(env_cpu(env), &val, va, size);
+    decode->len += size;
+    
+    return val;
+}
+
+static inline uint8_t decode_byte(CPUX86State *env, struct x86_decode *decode)
+{
+    return (uint8_t)decode_bytes(env, decode, 1);
+}
+
+static inline uint16_t decode_word(CPUX86State *env, struct x86_decode *decode)
+{
+    return (uint16_t)decode_bytes(env, decode, 2);
+}
+
+static inline uint32_t decode_dword(CPUX86State *env, struct x86_decode *decode)
+{
+    return (uint32_t)decode_bytes(env, decode, 4);
+}
+
+static inline uint64_t decode_qword(CPUX86State *env, struct x86_decode *decode)
+{
+    return decode_bytes(env, decode, 8);
+}
+
+static void decode_modrm_rm(CPUX86State *env, struct x86_decode *decode,
+                            struct x86_decode_op *op)
+{
+    op->type = X86_VAR_RM;
+}
+
+static void decode_modrm_reg(CPUX86State *env, struct x86_decode *decode,
+                             struct x86_decode_op *op)
+{
+    op->type = X86_VAR_REG;
+    op->reg = decode->modrm.reg;
+    op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.r,
+                          decode->operand_size);
+}
+
+static void decode_rax(CPUX86State *env, struct x86_decode *decode,
+                       struct x86_decode_op *op)
+{
+    op->type = X86_VAR_REG;
+    op->reg = R_EAX;
+    /* Since reg is always AX, REX prefix has no impact. */
+    op->ptr = get_reg_ref(env, op->reg, false, 0,
+                          decode->operand_size);
+}
+
+static inline void decode_immediate(CPUX86State *env, struct x86_decode *decode,
+                                    struct x86_decode_op *var, int size)
+{
+    var->type = X86_VAR_IMMEDIATE;
+    var->size = size;
+    switch (size) {
+    case 1:
+        var->val = decode_byte(env, decode);
+        break;
+    case 2:
+        var->val = decode_word(env, decode);
+        break;
+    case 4:
+        var->val = decode_dword(env, decode);
+        break;
+    case 8:
+        var->val = decode_qword(env, decode);
+        break;
+    default:
+        VM_PANIC_EX("bad size %d\n", size);
+    }
+}
+
+static void decode_imm8(CPUX86State *env, struct x86_decode *decode,
+                        struct x86_decode_op *op)
+{
+    decode_immediate(env, decode, op, 1);
+    op->type = X86_VAR_IMMEDIATE;
+}
+
+static void decode_imm8_signed(CPUX86State *env, struct x86_decode *decode,
+                               struct x86_decode_op *op)
+{
+    decode_immediate(env, decode, op, 1);
+    op->val = sign(op->val, 1);
+    op->type = X86_VAR_IMMEDIATE;
+}
+
+static void decode_imm16(CPUX86State *env, struct x86_decode *decode,
+                         struct x86_decode_op *op)
+{
+    decode_immediate(env, decode, op, 2);
+    op->type = X86_VAR_IMMEDIATE;
+}
+
+
+static void decode_imm(CPUX86State *env, struct x86_decode *decode,
+                       struct x86_decode_op *op)
+{
+    if (8 == decode->operand_size) {
+        decode_immediate(env, decode, op, 4);
+        op->val = sign(op->val, decode->operand_size);
+    } else {
+        decode_immediate(env, decode, op, decode->operand_size);
+    }
+    op->type = X86_VAR_IMMEDIATE;
+}
+
+static void decode_imm_signed(CPUX86State *env, struct x86_decode *decode,
+                              struct x86_decode_op *op)
+{
+    decode_immediate(env, decode, op, decode->operand_size);
+    op->val = sign(op->val, decode->operand_size);
+    op->type = X86_VAR_IMMEDIATE;
+}
+
+static void decode_imm_1(CPUX86State *env, struct x86_decode *decode,
+                         struct x86_decode_op *op)
+{
+    op->type = X86_VAR_IMMEDIATE;
+    op->val = 1;
+}
+
+static void decode_imm_0(CPUX86State *env, struct x86_decode *decode,
+                         struct x86_decode_op *op)
+{
+    op->type = X86_VAR_IMMEDIATE;
+    op->val = 0;
+}
+
+
+static void decode_pushseg(CPUX86State *env, struct x86_decode *decode)
+{
+    uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0];
+    
+    decode->op[0].type = X86_VAR_REG;
+    switch (op) {
+    case 0xe:
+        decode->op[0].reg = R_CS;
+        break;
+    case 0x16:
+        decode->op[0].reg = R_SS;
+        break;
+    case 0x1e:
+        decode->op[0].reg = R_DS;
+        break;
+    case 0x06:
+        decode->op[0].reg = R_ES;
+        break;
+    case 0xa0:
+        decode->op[0].reg = R_FS;
+        break;
+    case 0xa8:
+        decode->op[0].reg = R_GS;
+        break;
+    }
+}
+
+static void decode_popseg(CPUX86State *env, struct x86_decode *decode)
+{
+    uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0];
+    
+    decode->op[0].type = X86_VAR_REG;
+    switch (op) {
+    case 0xf:
+        decode->op[0].reg = R_CS;
+        break;
+    case 0x17:
+        decode->op[0].reg = R_SS;
+        break;
+    case 0x1f:
+        decode->op[0].reg = R_DS;
+        break;
+    case 0x07:
+        decode->op[0].reg = R_ES;
+        break;
+    case 0xa1:
+        decode->op[0].reg = R_FS;
+        break;
+    case 0xa9:
+        decode->op[0].reg = R_GS;
+        break;
+    }
+}
+
+static void decode_incgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_REG;
+    decode->op[0].reg = decode->opcode[0] - 0x40;
+    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
+                                    decode->rex.b, decode->operand_size);
+}
+
+static void decode_decgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_REG;
+    decode->op[0].reg = decode->opcode[0] - 0x48;
+    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
+                                    decode->rex.b, decode->operand_size);
+}
+
+static void decode_incgroup2(CPUX86State *env, struct x86_decode *decode)
+{
+    if (!decode->modrm.reg) {
+        decode->cmd = X86_DECODE_CMD_INC;
+    } else if (1 == decode->modrm.reg) {
+        decode->cmd = X86_DECODE_CMD_DEC;
+    }
+}
+
+static void decode_pushgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_REG;
+    decode->op[0].reg = decode->opcode[0] - 0x50;
+    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
+                                    decode->rex.b, decode->operand_size);
+}
+
+static void decode_popgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_REG;
+    decode->op[0].reg = decode->opcode[0] - 0x58;
+    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
+                                    decode->rex.b, decode->operand_size);
+}
+
+static void decode_jxx(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->displacement = decode_bytes(env, decode, decode->operand_size);
+    decode->displacement_size = decode->operand_size;
+}
+
+static void decode_farjmp(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_IMMEDIATE;
+    decode->op[0].val = decode_bytes(env, decode, decode->operand_size);
+    decode->displacement = decode_word(env, decode);
+}
+
+static void decode_addgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    enum x86_decode_cmd group[] = {
+        X86_DECODE_CMD_ADD,
+        X86_DECODE_CMD_OR,
+        X86_DECODE_CMD_ADC,
+        X86_DECODE_CMD_SBB,
+        X86_DECODE_CMD_AND,
+        X86_DECODE_CMD_SUB,
+        X86_DECODE_CMD_XOR,
+        X86_DECODE_CMD_CMP
+    };
+    decode->cmd = group[decode->modrm.reg];
+}
+
+static void decode_rotgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    enum x86_decode_cmd group[] = {
+        X86_DECODE_CMD_ROL,
+        X86_DECODE_CMD_ROR,
+        X86_DECODE_CMD_RCL,
+        X86_DECODE_CMD_RCR,
+        X86_DECODE_CMD_SHL,
+        X86_DECODE_CMD_SHR,
+        X86_DECODE_CMD_SHL,
+        X86_DECODE_CMD_SAR
+    };
+    decode->cmd = group[decode->modrm.reg];
+}
+
+static void decode_f7group(CPUX86State *env, struct x86_decode *decode)
+{
+    enum x86_decode_cmd group[] = {
+        X86_DECODE_CMD_TST,
+        X86_DECODE_CMD_TST,
+        X86_DECODE_CMD_NOT,
+        X86_DECODE_CMD_NEG,
+        X86_DECODE_CMD_MUL,
+        X86_DECODE_CMD_IMUL_1,
+        X86_DECODE_CMD_DIV,
+        X86_DECODE_CMD_IDIV
+    };
+    decode->cmd = group[decode->modrm.reg];
+    decode_modrm_rm(env, decode, &decode->op[0]);
+
+    switch (decode->modrm.reg) {
+    case 0:
+    case 1:
+        decode_imm(env, decode, &decode->op[1]);
+        break;
+    case 2:
+        break;
+    case 3:
+        decode->op[1].type = X86_VAR_IMMEDIATE;
+        decode->op[1].val = 0;
+        break;
+    default:
+        break;
+    }
+}
+
+static void decode_xchgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_REG;
+    decode->op[0].reg = decode->opcode[0] - 0x90;
+    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
+                                    decode->rex.b, decode->operand_size);
+}
+
+static void decode_movgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_REG;
+    decode->op[0].reg = decode->opcode[0] - 0xb8;
+    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
+                                    decode->rex.b, decode->operand_size);
+    decode_immediate(env, decode, &decode->op[1], decode->operand_size);
+}
+
+static void fetch_moffs(CPUX86State *env, struct x86_decode *decode,
+                        struct x86_decode_op *op)
+{
+    op->type = X86_VAR_OFFSET;
+    op->ptr = decode_bytes(env, decode, decode->addressing_size);
+}
+
+static void decode_movgroup8(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_REG;
+    decode->op[0].reg = decode->opcode[0] - 0xb0;
+    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
+                                    decode->rex.b, decode->operand_size);
+    decode_immediate(env, decode, &decode->op[1], decode->operand_size);
+}
+
+static void decode_rcx(CPUX86State *env, struct x86_decode *decode,
+                       struct x86_decode_op *op)
+{
+    op->type = X86_VAR_REG;
+    op->reg = R_ECX;
+    op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.b,
+                          decode->operand_size);
+}
+
+struct decode_tbl {
+    uint8_t opcode;
+    enum x86_decode_cmd cmd;
+    uint8_t operand_size;
+    bool is_modrm;
+    void (*decode_op1)(CPUX86State *env, struct x86_decode *decode,
+                       struct x86_decode_op *op1);
+    void (*decode_op2)(CPUX86State *env, struct x86_decode *decode,
+                       struct x86_decode_op *op2);
+    void (*decode_op3)(CPUX86State *env, struct x86_decode *decode,
+                       struct x86_decode_op *op3);
+    void (*decode_op4)(CPUX86State *env, struct x86_decode *decode,
+                       struct x86_decode_op *op4);
+    void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode);
+    uint32_t flags_mask;
+};
+
+struct decode_x87_tbl {
+    uint8_t opcode;
+    uint8_t modrm_reg;
+    uint8_t modrm_mod;
+    enum x86_decode_cmd cmd;
+    uint8_t operand_size;
+    bool rev;
+    bool pop;
+    void (*decode_op1)(CPUX86State *env, struct x86_decode *decode,
+                       struct x86_decode_op *op1);
+    void (*decode_op2)(CPUX86State *env, struct x86_decode *decode,
+                       struct x86_decode_op *op2);
+    void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode);
+    uint32_t flags_mask;
+};
+
+struct decode_tbl invl_inst = {0x0, 0, 0, false, NULL, NULL, NULL, NULL,
+                               decode_invalid};
+
+struct decode_tbl _decode_tbl1[256];
+struct decode_tbl _decode_tbl2[256];
+struct decode_x87_tbl _decode_tbl3[256];
+
+static void decode_x87_ins(CPUX86State *env, struct x86_decode *decode)
+{
+    struct decode_x87_tbl *decoder;
+    
+    decode->is_fpu = true;
+    int mode = decode->modrm.mod == 3 ? 1 : 0;
+    int index = ((decode->opcode[0] & 0xf) << 4) | (mode << 3) |
+                 decode->modrm.reg;
+
+    decoder = &_decode_tbl3[index];
+    
+    decode->cmd = decoder->cmd;
+    if (decoder->operand_size) {
+        decode->operand_size = decoder->operand_size;
+    }
+    decode->flags_mask = decoder->flags_mask;
+    decode->fpop_stack = decoder->pop;
+    decode->frev = decoder->rev;
+    
+    if (decoder->decode_op1) {
+        decoder->decode_op1(env, decode, &decode->op[0]);
+    }
+    if (decoder->decode_op2) {
+        decoder->decode_op2(env, decode, &decode->op[1]);
+    }
+    if (decoder->decode_postfix) {
+        decoder->decode_postfix(env, decode);
+    }
+
+    VM_PANIC_ON_EX(!decode->cmd, "x87 opcode %x %x (%x %x) not decoded\n",
+                   decode->opcode[0], decode->modrm.modrm, decoder->modrm_reg,
+                   decoder->modrm_mod);
+}
+
+static void decode_ffgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    enum x86_decode_cmd group[] = {
+        X86_DECODE_CMD_INC,
+        X86_DECODE_CMD_DEC,
+        X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT,
+        X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT,
+        X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT,
+        X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT,
+        X86_DECODE_CMD_PUSH,
+        X86_DECODE_CMD_INVL,
+        X86_DECODE_CMD_INVL
+    };
+    decode->cmd = group[decode->modrm.reg];
+    if (decode->modrm.reg > 2) {
+        decode->flags_mask = 0;
+    }
+}
+
+static void decode_sldtgroup(CPUX86State *env, struct x86_decode *decode)
+{
+
+    enum x86_decode_cmd group[] = {
+        X86_DECODE_CMD_SLDT,
+        X86_DECODE_CMD_STR,
+        X86_DECODE_CMD_LLDT,
+        X86_DECODE_CMD_LTR,
+        X86_DECODE_CMD_VERR,
+        X86_DECODE_CMD_VERW,
+        X86_DECODE_CMD_INVL,
+        X86_DECODE_CMD_INVL
+    };
+    decode->cmd = group[decode->modrm.reg];
+}
+
+static void decode_lidtgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    enum x86_decode_cmd group[] = {
+        X86_DECODE_CMD_SGDT,
+        X86_DECODE_CMD_SIDT,
+        X86_DECODE_CMD_LGDT,
+        X86_DECODE_CMD_LIDT,
+        X86_DECODE_CMD_SMSW,
+        X86_DECODE_CMD_LMSW,
+        X86_DECODE_CMD_LMSW,
+        X86_DECODE_CMD_INVLPG
+    };
+    decode->cmd = group[decode->modrm.reg];
+    if (0xf9 == decode->modrm.modrm) {
+        decode->opcode[decode->len++] = decode->modrm.modrm;
+        decode->cmd = X86_DECODE_CMD_RDTSCP;
+    }
+}
+
+static void decode_btgroup(CPUX86State *env, struct x86_decode *decode)
+{
+    enum x86_decode_cmd group[] = {
+        X86_DECODE_CMD_INVL,
+        X86_DECODE_CMD_INVL,
+        X86_DECODE_CMD_INVL,
+        X86_DECODE_CMD_INVL,
+        X86_DECODE_CMD_BT,
+        X86_DECODE_CMD_BTS,
+        X86_DECODE_CMD_BTR,
+        X86_DECODE_CMD_BTC
+    };
+    decode->cmd = group[decode->modrm.reg];
+}
+
+static void decode_x87_general(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->is_fpu = true;
+}
+
+static void decode_x87_modrm_floatp(CPUX86State *env, struct x86_decode *decode,
+                                    struct x86_decode_op *op)
+{
+    op->type = X87_VAR_FLOATP;
+}
+
+static void decode_x87_modrm_intp(CPUX86State *env, struct x86_decode *decode,
+                                  struct x86_decode_op *op)
+{
+    op->type = X87_VAR_INTP;
+}
+
+static void decode_x87_modrm_bytep(CPUX86State *env, struct x86_decode *decode,
+                                   struct x86_decode_op *op)
+{
+    op->type = X87_VAR_BYTEP;
+}
+
+static void decode_x87_modrm_st0(CPUX86State *env, struct x86_decode *decode,
+                                 struct x86_decode_op *op)
+{
+    op->type = X87_VAR_REG;
+    op->reg = 0;
+}
+
+static void decode_decode_x87_modrm_st0(CPUX86State *env,
+                                        struct x86_decode *decode,
+                                        struct x86_decode_op *op)
+{
+    op->type = X87_VAR_REG;
+    op->reg = decode->modrm.modrm & 7;
+}
+
+
+static void decode_aegroup(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->is_fpu = true;
+    switch (decode->modrm.reg) {
+    case 0:
+        decode->cmd = X86_DECODE_CMD_FXSAVE;
+        decode_x87_modrm_bytep(env, decode, &decode->op[0]);
+        break;
+    case 1:
+        decode_x87_modrm_bytep(env, decode, &decode->op[0]);
+        decode->cmd = X86_DECODE_CMD_FXRSTOR;
+        break;
+    case 5:
+        if (decode->modrm.modrm == 0xe8) {
+            decode->cmd = X86_DECODE_CMD_LFENCE;
+        } else {
+            VM_PANIC("xrstor");
+        }
+        break;
+    case 6:
+        VM_PANIC_ON(decode->modrm.modrm != 0xf0);
+        decode->cmd = X86_DECODE_CMD_MFENCE;
+        break;
+    case 7:
+        if (decode->modrm.modrm == 0xf8) {
+            decode->cmd = X86_DECODE_CMD_SFENCE;
+        } else {
+            decode->cmd = X86_DECODE_CMD_CLFLUSH;
+        }
+        break;
+    default:
+        VM_PANIC_EX("0xae: reg %d\n", decode->modrm.reg);
+        break;
+    }
+}
+
+static void decode_bswap(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_REG;
+    decode->op[0].reg = decode->opcode[1] - 0xc8;
+    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
+                                    decode->rex.b, decode->operand_size);
+}
+
+static void decode_d9_4(CPUX86State *env, struct x86_decode *decode)
+{
+    switch (decode->modrm.modrm) {
+    case 0xe0:
+        /* FCHS */
+        decode->cmd = X86_DECODE_CMD_FCHS;
+        break;
+    case 0xe1:
+        decode->cmd = X86_DECODE_CMD_FABS;
+        break;
+    case 0xe4:
+        VM_PANIC("FTST");
+        break;
+    case 0xe5:
+        /* FXAM */
+        decode->cmd = X86_DECODE_CMD_FXAM;
+        break;
+    default:
+        VM_PANIC("FLDENV");
+        break;
+    }
+}
+
+static void decode_db_4(CPUX86State *env, struct x86_decode *decode)
+{
+    switch (decode->modrm.modrm) {
+    case 0xe0:
+        VM_PANIC_EX("unhandled FNENI: %x %x\n", decode->opcode[0],
+                    decode->modrm.modrm);
+        break;
+    case 0xe1:
+        VM_PANIC_EX("unhandled FNDISI: %x %x\n", decode->opcode[0],
+                    decode->modrm.modrm);
+        break;
+    case 0xe2:
+        VM_PANIC_EX("unhandled FCLEX: %x %x\n", decode->opcode[0],
+                    decode->modrm.modrm);
+        break;
+    case 0xe3:
+        decode->cmd = X86_DECODE_CMD_FNINIT;
+        break;
+    case 0xe4:
+        decode->cmd = X86_DECODE_CMD_FNSETPM;
+        break;
+    default:
+        VM_PANIC_EX("unhandled fpu opcode: %x %x\n", decode->opcode[0],
+                    decode->modrm.modrm);
+        break;
+    }
+}
+
+
+#define RFLAGS_MASK_NONE    0
+#define RFLAGS_MASK_OSZAPC  (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
+#define RFLAGS_MASK_LAHF    (CC_S | CC_Z | CC_A | CC_P | CC_C)
+#define RFLAGS_MASK_CF      (CC_C)
+#define RFLAGS_MASK_IF      (IF_MASK)
+#define RFLAGS_MASK_TF      (TF_MASK)
+#define RFLAGS_MASK_DF      (DF_MASK)
+#define RFLAGS_MASK_ZF      (CC_Z)
+
+struct decode_tbl _1op_inst[] = {
+    {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL,
+     NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x1, X86_DECODE_CMD_ADD, 0, true, decode_modrm_rm, decode_modrm_reg, NULL,
+     NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x2, X86_DECODE_CMD_ADD, 1, true, decode_modrm_reg, decode_modrm_rm, NULL,
+     NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x3, X86_DECODE_CMD_ADD, 0, true, decode_modrm_reg, decode_modrm_rm, NULL,
+     NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x4, X86_DECODE_CMD_ADD, 1, false, decode_rax, decode_imm8, NULL, NULL,
+     NULL, RFLAGS_MASK_OSZAPC},
+    {0x5, X86_DECODE_CMD_ADD, 0, false, decode_rax, decode_imm, NULL, NULL,
+     NULL, RFLAGS_MASK_OSZAPC},
+    {0x6, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL,
+     decode_pushseg, RFLAGS_MASK_NONE},
+    {0x7, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL,
+     decode_popseg, RFLAGS_MASK_NONE},
+    {0x8, X86_DECODE_CMD_OR, 1, true, decode_modrm_rm, decode_modrm_reg, NULL,
+     NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x9, X86_DECODE_CMD_OR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL,
+     NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xa, X86_DECODE_CMD_OR, 1, true, decode_modrm_reg, decode_modrm_rm, NULL,
+     NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xb, X86_DECODE_CMD_OR, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xc, X86_DECODE_CMD_OR, 1, false, decode_rax, decode_imm8,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xd, X86_DECODE_CMD_OR, 0, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0xe, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
+    {0xf, X86_DECODE_CMD_POP_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
+
+    {0x10, X86_DECODE_CMD_ADC, 1, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x11, X86_DECODE_CMD_ADC, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x12, X86_DECODE_CMD_ADC, 1, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x13, X86_DECODE_CMD_ADC, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x14, X86_DECODE_CMD_ADC, 1, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x15, X86_DECODE_CMD_ADC, 0, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0x16, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
+    {0x17, X86_DECODE_CMD_POP_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
+
+    {0x18, X86_DECODE_CMD_SBB, 1, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x19, X86_DECODE_CMD_SBB, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x1a, X86_DECODE_CMD_SBB, 1, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x1b, X86_DECODE_CMD_SBB, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x1c, X86_DECODE_CMD_SBB, 1, false, decode_rax, decode_imm8,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x1d, X86_DECODE_CMD_SBB, 0, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0x1e, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
+    {0x1f, X86_DECODE_CMD_POP_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
+
+    {0x20, X86_DECODE_CMD_AND, 1, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x21, X86_DECODE_CMD_AND, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x22, X86_DECODE_CMD_AND, 1, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x23, X86_DECODE_CMD_AND, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x24, X86_DECODE_CMD_AND, 1, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x25, X86_DECODE_CMD_AND, 0, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x28, X86_DECODE_CMD_SUB, 1, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x29, X86_DECODE_CMD_SUB, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x2a, X86_DECODE_CMD_SUB, 1, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x2b, X86_DECODE_CMD_SUB, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x2c, X86_DECODE_CMD_SUB, 1, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x2d, X86_DECODE_CMD_SUB, 0, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x2f, X86_DECODE_CMD_DAS, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x30, X86_DECODE_CMD_XOR, 1, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x31, X86_DECODE_CMD_XOR, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x32, X86_DECODE_CMD_XOR, 1, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x33, X86_DECODE_CMD_XOR, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x34, X86_DECODE_CMD_XOR, 1, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x35, X86_DECODE_CMD_XOR, 0, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0x38, X86_DECODE_CMD_CMP, 1, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x39, X86_DECODE_CMD_CMP, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x3a, X86_DECODE_CMD_CMP, 1, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x3b, X86_DECODE_CMD_CMP, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x3c, X86_DECODE_CMD_CMP, 1, false, decode_rax, decode_imm8,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x3d, X86_DECODE_CMD_CMP, 0, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0x3f, X86_DECODE_CMD_AAS, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0x40, X86_DECODE_CMD_INC, 0, false,
+     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
+    {0x41, X86_DECODE_CMD_INC, 0, false,
+     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
+    {0x42, X86_DECODE_CMD_INC, 0, false,
+     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
+    {0x43, X86_DECODE_CMD_INC, 0, false,
+     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
+    {0x44, X86_DECODE_CMD_INC, 0, false,
+     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
+    {0x45, X86_DECODE_CMD_INC, 0, false,
+     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
+    {0x46, X86_DECODE_CMD_INC, 0, false,
+     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
+    {0x47, X86_DECODE_CMD_INC, 0, false,
+     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
+
+    {0x48, X86_DECODE_CMD_DEC, 0, false,
+     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
+    {0x49, X86_DECODE_CMD_DEC, 0, false,
+     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
+    {0x4a, X86_DECODE_CMD_DEC, 0, false,
+     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
+    {0x4b, X86_DECODE_CMD_DEC, 0, false,
+     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
+    {0x4c, X86_DECODE_CMD_DEC, 0, false,
+     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
+    {0x4d, X86_DECODE_CMD_DEC, 0, false,
+     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
+    {0x4e, X86_DECODE_CMD_DEC, 0, false,
+     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
+    {0x4f, X86_DECODE_CMD_DEC, 0, false,
+     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
+
+    {0x50, X86_DECODE_CMD_PUSH, 0, false,
+     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
+    {0x51, X86_DECODE_CMD_PUSH, 0, false,
+     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
+    {0x52, X86_DECODE_CMD_PUSH, 0, false,
+     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
+    {0x53, X86_DECODE_CMD_PUSH, 0, false,
+     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
+    {0x54, X86_DECODE_CMD_PUSH, 0, false,
+     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
+    {0x55, X86_DECODE_CMD_PUSH, 0, false,
+     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
+    {0x56, X86_DECODE_CMD_PUSH, 0, false,
+     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
+    {0x57, X86_DECODE_CMD_PUSH, 0, false,
+     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
+
+    {0x58, X86_DECODE_CMD_POP, 0, false,
+     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
+    {0x59, X86_DECODE_CMD_POP, 0, false,
+     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
+    {0x5a, X86_DECODE_CMD_POP, 0, false,
+     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
+    {0x5b, X86_DECODE_CMD_POP, 0, false,
+     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
+    {0x5c, X86_DECODE_CMD_POP, 0, false,
+     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
+    {0x5d, X86_DECODE_CMD_POP, 0, false,
+     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
+    {0x5e, X86_DECODE_CMD_POP, 0, false,
+     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
+    {0x5f, X86_DECODE_CMD_POP, 0, false,
+     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
+
+    {0x60, X86_DECODE_CMD_PUSHA, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x61, X86_DECODE_CMD_POPA, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0x68, X86_DECODE_CMD_PUSH, 0, false, decode_imm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x6a, X86_DECODE_CMD_PUSH, 0, false, decode_imm8_signed,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x69, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg,
+     decode_modrm_rm, decode_imm, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x6b, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, decode_modrm_rm,
+     decode_imm8_signed, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0x6c, X86_DECODE_CMD_INS, 1, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x6d, X86_DECODE_CMD_INS, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x6e, X86_DECODE_CMD_OUTS, 1, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x6f, X86_DECODE_CMD_OUTS, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0x70, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x71, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x72, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x73, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x74, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x75, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x76, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x77, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x78, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x79, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x7a, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x7b, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x7c, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x7d, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x7e, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x7f, X86_DECODE_CMD_JXX, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+
+    {0x80, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8,
+     NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC},
+    {0x81, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm,
+     NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC},
+    {0x82, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8,
+     NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC},
+    {0x83, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8_signed,
+     NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC},
+    {0x84, X86_DECODE_CMD_TST, 1, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x85, X86_DECODE_CMD_TST, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0x86, X86_DECODE_CMD_XCHG, 1, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x87, X86_DECODE_CMD_XCHG, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x88, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x89, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x8a, X86_DECODE_CMD_MOV, 1, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x8b, X86_DECODE_CMD_MOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x8c, X86_DECODE_CMD_MOV_FROM_SEG, 0, true, decode_modrm_rm,
+     decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x8d, X86_DECODE_CMD_LEA, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x8e, X86_DECODE_CMD_MOV_TO_SEG, 0, true, decode_modrm_reg,
+     decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x8f, X86_DECODE_CMD_POP, 0, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0x90, X86_DECODE_CMD_NOP, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x91, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
+     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
+    {0x92, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
+     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
+    {0x93, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
+     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
+    {0x94, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
+     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
+    {0x95, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
+     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
+    {0x96, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
+     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
+    {0x97, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
+     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
+
+    {0x98, X86_DECODE_CMD_CBW, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x99, X86_DECODE_CMD_CWD, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0x9a, X86_DECODE_CMD_CALL_FAR, 0, false, NULL,
+     NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE},
+
+    {0x9c, X86_DECODE_CMD_PUSHF, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    /*{0x9d, X86_DECODE_CMD_POPF, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_POPF},*/
+    {0x9e, X86_DECODE_CMD_SAHF, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x9f, X86_DECODE_CMD_LAHF, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_LAHF},
+
+    {0xa0, X86_DECODE_CMD_MOV, 1, false, decode_rax, fetch_moffs,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xa1, X86_DECODE_CMD_MOV, 0, false, decode_rax, fetch_moffs,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xa2, X86_DECODE_CMD_MOV, 1, false, fetch_moffs, decode_rax,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xa3, X86_DECODE_CMD_MOV, 0, false, fetch_moffs, decode_rax,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xa4, X86_DECODE_CMD_MOVS, 1, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xa5, X86_DECODE_CMD_MOVS, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xa6, X86_DECODE_CMD_CMPS, 1, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xa7, X86_DECODE_CMD_CMPS, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xaa, X86_DECODE_CMD_STOS, 1, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xab, X86_DECODE_CMD_STOS, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xac, X86_DECODE_CMD_LODS, 1, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xad, X86_DECODE_CMD_LODS, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xae, X86_DECODE_CMD_SCAS, 1, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xaf, X86_DECODE_CMD_SCAS, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0xa8, X86_DECODE_CMD_TST, 1, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xa9, X86_DECODE_CMD_TST, 0, false, decode_rax, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0xb0, X86_DECODE_CMD_MOV, 1, false, NULL,
+     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
+    {0xb1, X86_DECODE_CMD_MOV, 1, false, NULL,
+     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
+    {0xb2, X86_DECODE_CMD_MOV, 1, false, NULL,
+     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
+    {0xb3, X86_DECODE_CMD_MOV, 1, false, NULL,
+     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
+    {0xb4, X86_DECODE_CMD_MOV, 1, false, NULL,
+     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
+    {0xb5, X86_DECODE_CMD_MOV, 1, false, NULL,
+     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
+    {0xb6, X86_DECODE_CMD_MOV, 1, false, NULL,
+     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
+    {0xb7, X86_DECODE_CMD_MOV, 1, false, NULL,
+     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
+
+    {0xb8, X86_DECODE_CMD_MOV, 0, false, NULL,
+     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
+    {0xb9, X86_DECODE_CMD_MOV, 0, false, NULL,
+     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
+    {0xba, X86_DECODE_CMD_MOV, 0, false, NULL,
+     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
+    {0xbb, X86_DECODE_CMD_MOV, 0, false, NULL,
+     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
+    {0xbc, X86_DECODE_CMD_MOV, 0, false, NULL,
+     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
+    {0xbd, X86_DECODE_CMD_MOV, 0, false, NULL,
+     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
+    {0xbe, X86_DECODE_CMD_MOV, 0, false, NULL,
+     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
+    {0xbf, X86_DECODE_CMD_MOV, 0, false, NULL,
+     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
+
+    {0xc0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8,
+     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
+    {0xc1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8,
+     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
+
+    {0xc2, X86_DECODE_RET_NEAR, 0, false, decode_imm16,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xc3, X86_DECODE_RET_NEAR, 0, false, NULL,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xc4, X86_DECODE_CMD_LES, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xc5, X86_DECODE_CMD_LDS, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xc6, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_imm8,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xc7, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_imm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xc8, X86_DECODE_CMD_ENTER, 0, false, decode_imm16, decode_imm8,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xc9, X86_DECODE_CMD_LEAVE, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xca, X86_DECODE_RET_FAR, 0, false, decode_imm16, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xcb, X86_DECODE_RET_FAR, 0, false, decode_imm_0, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xcd, X86_DECODE_CMD_INT, 0, false, decode_imm8, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    /*{0xcf, X86_DECODE_CMD_IRET, 0, false, NULL, NULL,
+     NULL, NULL, NULL, RFLAGS_MASK_IRET},*/
+
+    {0xd0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm_1,
+     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
+    {0xd1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm_1,
+     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
+    {0xd2, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_rcx,
+     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
+    {0xd3, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_rcx,
+     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
+
+    {0xd4, X86_DECODE_CMD_AAM, 0, false, decode_imm8,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xd5, X86_DECODE_CMD_AAD, 0, false, decode_imm8,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0xd7, X86_DECODE_CMD_XLAT, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xd8, X86_DECODE_CMD_INVL, 0, true, NULL,
+     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
+    {0xd9, X86_DECODE_CMD_INVL, 0, true, NULL,
+     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
+    {0xda, X86_DECODE_CMD_INVL, 0, true, NULL,
+     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
+    {0xdb, X86_DECODE_CMD_INVL, 0, true, NULL,
+     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
+    {0xdc, X86_DECODE_CMD_INVL, 0, true, NULL,
+     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
+    {0xdd, X86_DECODE_CMD_INVL, 0, true, NULL,
+     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
+    {0xde, X86_DECODE_CMD_INVL, 0, true, NULL,
+     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
+    {0xdf, X86_DECODE_CMD_INVL, 0, true, NULL,
+     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
+
+    {0xe0, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xe1, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xe2, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xe3, X86_DECODE_CMD_JCXZ, 1, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+
+    {0xe4, X86_DECODE_CMD_IN, 1, false, decode_imm8,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xe5, X86_DECODE_CMD_IN, 0, false, decode_imm8,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xe6, X86_DECODE_CMD_OUT, 1, false, decode_imm8,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xe7, X86_DECODE_CMD_OUT, 0, false, decode_imm8,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xe8, X86_DECODE_CMD_CALL_NEAR, 0, false, decode_imm_signed,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xe9, X86_DECODE_CMD_JMP_NEAR, 0, false, decode_imm_signed,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xea, X86_DECODE_CMD_JMP_FAR, 0, false,
+     NULL, NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE},
+    {0xeb, X86_DECODE_CMD_JMP_NEAR, 1, false, decode_imm8_signed,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xec, X86_DECODE_CMD_IN, 1, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xed, X86_DECODE_CMD_IN, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xee, X86_DECODE_CMD_OUT, 1, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xef, X86_DECODE_CMD_OUT, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xf4, X86_DECODE_CMD_HLT, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xf5, X86_DECODE_CMD_CMC, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF},
+
+    {0xf6, X86_DECODE_CMD_INVL, 1, true,
+     NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC},
+    {0xf7, X86_DECODE_CMD_INVL, 0, true,
+     NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC},
+
+    {0xf8, X86_DECODE_CMD_CLC, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF},
+    {0xf9, X86_DECODE_CMD_STC, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF},
+
+    {0xfa, X86_DECODE_CMD_CLI, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF},
+    {0xfb, X86_DECODE_CMD_STI, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF},
+    {0xfc, X86_DECODE_CMD_CLD, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF},
+    {0xfd, X86_DECODE_CMD_STD, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF},
+    {0xfe, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, decode_incgroup2, RFLAGS_MASK_OSZAPC},
+    {0xff, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm,
+     NULL, NULL, NULL, decode_ffgroup, RFLAGS_MASK_OSZAPC},
+};
+
+struct decode_tbl _2op_inst[] = {
+    {0x0, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm,
+     NULL, NULL, NULL, decode_sldtgroup, RFLAGS_MASK_NONE},
+    {0x1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm,
+     NULL, NULL, NULL, decode_lidtgroup, RFLAGS_MASK_NONE},
+    {0x6, X86_DECODE_CMD_CLTS, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_TF},
+    {0x9, X86_DECODE_CMD_WBINVD, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x18, X86_DECODE_CMD_PREFETCH, 0, true,
+     NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE},
+    {0x1f, X86_DECODE_CMD_NOP, 0, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x20, X86_DECODE_CMD_MOV_FROM_CR, 0, true, decode_modrm_rm,
+     decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x21, X86_DECODE_CMD_MOV_FROM_DR, 0, true, decode_modrm_rm,
+     decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x22, X86_DECODE_CMD_MOV_TO_CR, 0, true, decode_modrm_reg,
+     decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x23, X86_DECODE_CMD_MOV_TO_DR, 0, true, decode_modrm_reg,
+     decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x30, X86_DECODE_CMD_WRMSR, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x31, X86_DECODE_CMD_RDTSC, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x32, X86_DECODE_CMD_RDMSR, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x40, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x41, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x42, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x43, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x44, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x45, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x46, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x47, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x48, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x49, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x4a, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x4b, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x4c, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x4d, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x4e, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x4f, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x77, X86_DECODE_CMD_EMMS, 0, false,
+     NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE},
+    {0x82, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x83, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x84, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x85, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x86, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x87, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x88, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x89, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x8a, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x8b, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x8c, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x8d, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x8e, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x8f, X86_DECODE_CMD_JXX, 0, false,
+     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
+    {0x90, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x91, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x92, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x93, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x94, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x95, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x96, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x97, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x98, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x99, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x9a, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x9b, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x9c, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x9d, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x9e, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0x9f, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xb0, X86_DECODE_CMD_CMPXCHG, 1, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xb1, X86_DECODE_CMD_CMPXCHG, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xb6, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xb7, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xb8, X86_DECODE_CMD_POPCNT, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xbe, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xbf, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xa0, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
+    {0xa1, X86_DECODE_CMD_POP_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
+    {0xa2, X86_DECODE_CMD_CPUID, 0, false,
+     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xa3, X86_DECODE_CMD_BT, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_CF},
+    {0xa4, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg,
+     decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xa5, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg,
+     decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xa8, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
+    {0xa9, X86_DECODE_CMD_POP_SEG, 0, false, false,
+     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
+    {0xab, X86_DECODE_CMD_BTS, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_CF},
+    {0xac, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg,
+     decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xad, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg,
+     decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0xae, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm,
+     NULL, NULL, NULL, decode_aegroup, RFLAGS_MASK_NONE},
+
+    {0xaf, X86_DECODE_CMD_IMUL_2, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xb2, X86_DECODE_CMD_LSS, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xb3, X86_DECODE_CMD_BTR, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xba, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8,
+     NULL, NULL, decode_btgroup, RFLAGS_MASK_OSZAPC},
+    {0xbb, X86_DECODE_CMD_BTC, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xbc, X86_DECODE_CMD_BSF, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+    {0xbd, X86_DECODE_CMD_BSR, 0, true, decode_modrm_reg, decode_modrm_rm,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0xc1, X86_DECODE_CMD_XADD, 0, true, decode_modrm_rm, decode_modrm_reg,
+     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
+
+    {0xc7, X86_DECODE_CMD_CMPXCHG8B, 0, true, decode_modrm_rm,
+     NULL, NULL, NULL, NULL, RFLAGS_MASK_ZF},
+
+    {0xc8, X86_DECODE_CMD_BSWAP, 0, false,
+     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
+    {0xc9, X86_DECODE_CMD_BSWAP, 0, false,
+     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
+    {0xca, X86_DECODE_CMD_BSWAP, 0, false,
+     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
+    {0xcb, X86_DECODE_CMD_BSWAP, 0, false,
+     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
+    {0xcc, X86_DECODE_CMD_BSWAP, 0, false,
+     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
+    {0xcd, X86_DECODE_CMD_BSWAP, 0, false,
+     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
+    {0xce, X86_DECODE_CMD_BSWAP, 0, false,
+     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
+    {0xcf, X86_DECODE_CMD_BSWAP, 0, false,
+     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
+};
+
+struct decode_x87_tbl invl_inst_x87 = {0x0, 0, 0, 0, 0, false, false, NULL,
+                                       NULL, decode_invalid, 0};
+
+struct decode_x87_tbl _x87_inst[] = {
+    {0xd8, 0, 3, X86_DECODE_CMD_FADD, 10, false, false,
+     decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, decode_x87_modrm_st0,
+     decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 4, 3, X86_DECODE_CMD_FSUB, 10, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 5, 3, X86_DECODE_CMD_FSUB, 10, true, false, decode_x87_modrm_st0,
+     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0,
+     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 6, 3, X86_DECODE_CMD_FDIV, 10, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 7, 3, X86_DECODE_CMD_FDIV, 10, true, false, decode_x87_modrm_st0,
+     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xd8, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0,
+     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+
+    {0xd9, 0, 3, X86_DECODE_CMD_FLD, 10, false, false,
+     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 0, 0, X86_DECODE_CMD_FLD, 4, false, false,
+     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 1, 0, X86_DECODE_CMD_INVL, 10, false, false,
+     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 2, 3, X86_DECODE_CMD_INVL, 10, false, false,
+     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 2, 0, X86_DECODE_CMD_FST, 4, false, false,
+     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 3, 3, X86_DECODE_CMD_INVL, 10, false, false,
+     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 3, 0, X86_DECODE_CMD_FST, 4, false, true,
+     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 4, 3, X86_DECODE_CMD_INVL, 10, false, false,
+     decode_x87_modrm_st0, NULL, decode_d9_4, RFLAGS_MASK_NONE},
+    {0xd9, 4, 0, X86_DECODE_CMD_INVL, 4, false, false,
+     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 5, 3, X86_DECODE_CMD_FLDxx, 10, false, false, NULL, NULL, NULL,
+     RFLAGS_MASK_NONE},
+    {0xd9, 5, 0, X86_DECODE_CMD_FLDCW, 2, false, false,
+     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xd9, 7, 3, X86_DECODE_CMD_FNSTCW, 2, false, false,
+     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xd9, 7, 0, X86_DECODE_CMD_FNSTCW, 2, false, false,
+     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xda, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xda, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xda, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0,
+     decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xda, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xda, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xda, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xda, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
+     RFLAGS_MASK_NONE},
+    {0xda, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xda, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, decode_x87_modrm_st0,
+     decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xda, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0,
+     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xda, 6, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
+     RFLAGS_MASK_NONE},
+    {0xda, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xda, 7, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
+     RFLAGS_MASK_NONE},
+    {0xda, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0,
+     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+
+    {0xdb, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0,
+     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdb, 0, 0, X86_DECODE_CMD_FLD, 4, false, false,
+     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdb, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdb, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdb, 2, 0, X86_DECODE_CMD_FST, 4, false, false,
+     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdb, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdb, 3, 0, X86_DECODE_CMD_FST, 4, false, true,
+     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdb, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL,
+     decode_db_4, RFLAGS_MASK_NONE},
+    {0xdb, 4, 0, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
+     RFLAGS_MASK_NONE},
+    {0xdb, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdb, 5, 0, X86_DECODE_CMD_FLD, 10, false, false,
+     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdb, 7, 0, X86_DECODE_CMD_FST, 10, false, true,
+     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xdc, 0, 3, X86_DECODE_CMD_FADD, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 0, 0, X86_DECODE_CMD_FADD, 8, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 1, 0, X86_DECODE_CMD_FMUL, 8, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 4, 3, X86_DECODE_CMD_FSUB, 10, true, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 4, 0, X86_DECODE_CMD_FSUB, 8, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 5, 3, X86_DECODE_CMD_FSUB, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 5, 0, X86_DECODE_CMD_FSUB, 8, true, false,
+     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 6, 3, X86_DECODE_CMD_FDIV, 10, true, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 6, 0, X86_DECODE_CMD_FDIV, 8, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 7, 3, X86_DECODE_CMD_FDIV, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdc, 7, 0, X86_DECODE_CMD_FDIV, 8, true, false,
+     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
+
+    {0xdd, 0, 0, X86_DECODE_CMD_FLD, 8, false, false,
+     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 2, 3, X86_DECODE_CMD_FST, 10, false, false,
+     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 2, 0, X86_DECODE_CMD_FST, 8, false, false,
+     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 3, 3, X86_DECODE_CMD_FST, 10, false, true,
+     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 3, 0, X86_DECODE_CMD_FST, 8, false, true,
+     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 4, 3, X86_DECODE_CMD_FUCOM, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 4, 0, X86_DECODE_CMD_FRSTOR, 8, false, false,
+     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 7, 0, X86_DECODE_CMD_FNSTSW, 0, false, false,
+     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdd, 7, 3, X86_DECODE_CMD_FNSTSW, 0, false, false,
+     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
+
+    {0xde, 0, 3, X86_DECODE_CMD_FADD, 10, false, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xde, 0, 0, X86_DECODE_CMD_FADD, 2, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xde, 1, 3, X86_DECODE_CMD_FMUL, 10, false, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xde, 1, 0, X86_DECODE_CMD_FMUL, 2, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xde, 4, 3, X86_DECODE_CMD_FSUB, 10, true, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xde, 4, 0, X86_DECODE_CMD_FSUB, 2, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xde, 5, 3, X86_DECODE_CMD_FSUB, 10, false, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xde, 5, 0, X86_DECODE_CMD_FSUB, 2, true, false,
+     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xde, 6, 3, X86_DECODE_CMD_FDIV, 10, true, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xde, 6, 0, X86_DECODE_CMD_FDIV, 2, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+    {0xde, 7, 3, X86_DECODE_CMD_FDIV, 10, false, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xde, 7, 0, X86_DECODE_CMD_FDIV, 2, true, false,
+     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
+
+    {0xdf, 0, 0, X86_DECODE_CMD_FLD, 2, false, false,
+     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdf, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdf, 2, 3, X86_DECODE_CMD_FST, 10, false, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdf, 2, 0, X86_DECODE_CMD_FST, 2, false, false,
+     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdf, 3, 3, X86_DECODE_CMD_FST, 10, false, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdf, 3, 0, X86_DECODE_CMD_FST, 2, false, true,
+     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdf, 4, 3, X86_DECODE_CMD_FNSTSW, 2, false, true,
+     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdf, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, true,
+     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
+    {0xdf, 5, 0, X86_DECODE_CMD_FLD, 8, false, false,
+     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
+    {0xdf, 7, 0, X86_DECODE_CMD_FST, 8, false, true,
+     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
+};
+
+void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode,
+                          struct x86_decode_op *op)
+{
+    target_ulong ptr = 0;
+    X86Seg seg = R_DS;
+
+    if (!decode->modrm.mod && 6 == decode->modrm.rm) {
+        ptr = decode->displacement;
+        goto calc_addr;
+    }
+
+    if (decode->displacement_size) {
+        ptr = sign(decode->displacement, decode->displacement_size);
+    }
+
+    switch (decode->modrm.rm) {
+    case 0:
+        ptr += BX(env) + SI(env);
+        break;
+    case 1:
+        ptr += BX(env) + DI(env);
+        break;
+    case 2:
+        ptr += BP(env) + SI(env);
+        seg = R_SS;
+        break;
+    case 3:
+        ptr += BP(env) + DI(env);
+        seg = R_SS;
+        break;
+    case 4:
+        ptr += SI(env);
+        break;
+    case 5:
+        ptr += DI(env);
+        break;
+    case 6:
+        ptr += BP(env);
+        seg = R_SS;
+        break;
+    case 7:
+        ptr += BX(env);
+        break;
+    }
+calc_addr:
+    if (X86_DECODE_CMD_LEA == decode->cmd) {
+        op->ptr = (uint16_t)ptr;
+    } else {
+        op->ptr = decode_linear_addr(env, decode, (uint16_t)ptr, seg);
+    }
+}
+
+target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present,
+                         int is_extended, int size)
+{
+    target_ulong ptr = 0;
+
+    if (is_extended) {
+        reg |= R_R8;
+    }
+
+    switch (size) {
+    case 1:
+        if (is_extended || reg < 4 || rex_present) {
+            ptr = (target_ulong)&RL(env, reg);
+        } else {
+            ptr = (target_ulong)&RH(env, reg - 4);
+        }
+        break;
+    default:
+        ptr = (target_ulong)&RRX(env, reg);
+        break;
+    }
+    return ptr;
+}
+
+target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present,
+                         int is_extended, int size)
+{
+    target_ulong val = 0;
+    memcpy(&val,
+           (void *)get_reg_ref(env, reg, rex_present, is_extended, size),
+           size);
+    return val;
+}
+
+static target_ulong get_sib_val(CPUX86State *env, struct x86_decode *decode,
+                          X86Seg *sel)
+{
+    target_ulong base = 0;
+    target_ulong scaled_index = 0;
+    int addr_size = decode->addressing_size;
+    int base_reg = decode->sib.base;
+    int index_reg = decode->sib.index;
+
+    *sel = R_DS;
+
+    if (decode->modrm.mod || base_reg != R_EBP) {
+        if (decode->rex.b) {
+            base_reg |= R_R8;
+        }
+        if (base_reg == R_ESP || base_reg == R_EBP) {
+            *sel = R_SS;
+        }
+        base = get_reg_val(env, decode->sib.base, decode->rex.rex,
+                           decode->rex.b, addr_size);
+    }
+
+    if (decode->rex.x) {
+        index_reg |= R_R8;
+    }
+
+    if (index_reg != R_ESP) {
+        scaled_index = get_reg_val(env, index_reg, decode->rex.rex,
+                                   decode->rex.x, addr_size) <<
+                                   decode->sib.scale;
+    }
+    return base + scaled_index;
+}
+
+void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode,
+                          struct x86_decode_op *op)
+{
+    X86Seg seg = R_DS;
+    target_ulong ptr = 0;
+    int addr_size = decode->addressing_size;
+
+    if (decode->displacement_size) {
+        ptr = sign(decode->displacement, decode->displacement_size);
+    }
+
+    if (4 == decode->modrm.rm) {
+        ptr += get_sib_val(env, decode, &seg);
+    } else if (!decode->modrm.mod && 5 == decode->modrm.rm) {
+        if (x86_is_long_mode(env_cpu(env))) {
+            ptr += env->eip + decode->len;
+        } else {
+            ptr = decode->displacement;
+        }
+    } else {
+        if (decode->modrm.rm == R_EBP || decode->modrm.rm == R_ESP) {
+            seg = R_SS;
+        }
+        ptr += get_reg_val(env, decode->modrm.rm, decode->rex.rex,
+                           decode->rex.b, addr_size);
+    }
+
+    if (X86_DECODE_CMD_LEA == decode->cmd) {
+        op->ptr = (uint32_t)ptr;
+    } else {
+        op->ptr = decode_linear_addr(env, decode, (uint32_t)ptr, seg);
+    }
+}
+
+void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode,
+                          struct x86_decode_op *op)
+{
+    X86Seg seg = R_DS;
+    int32_t offset = 0;
+    int mod = decode->modrm.mod;
+    int rm = decode->modrm.rm;
+    target_ulong ptr;
+    int src = decode->modrm.rm;
+
+    if (decode->displacement_size) {
+        offset = sign(decode->displacement, decode->displacement_size);
+    }
+
+    if (4 == rm) {
+        ptr = get_sib_val(env, decode, &seg) + offset;
+    } else if (0 == mod && 5 == rm) {
+        ptr = env->eip + decode->len + (int32_t) offset;
+    } else {
+        ptr = get_reg_val(env, src, decode->rex.rex, decode->rex.b, 8) +
+              (int64_t) offset;
+    }
+
+    if (X86_DECODE_CMD_LEA == decode->cmd) {
+        op->ptr = ptr;
+    } else {
+        op->ptr = decode_linear_addr(env, decode, ptr, seg);
+    }
+}
+
+
+void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,
+                        struct x86_decode_op *op)
+{
+    if (3 == decode->modrm.mod) {
+        op->reg = decode->modrm.reg;
+        op->type = X86_VAR_REG;
+        op->ptr = get_reg_ref(env, decode->modrm.rm, decode->rex.rex,
+                              decode->rex.b, decode->operand_size);
+        return;
+    }
+
+    switch (decode->addressing_size) {
+    case 2:
+        calc_modrm_operand16(env, decode, op);
+        break;
+    case 4:
+        calc_modrm_operand32(env, decode, op);
+        break;
+    case 8:
+        calc_modrm_operand64(env, decode, op);
+        break;
+    default:
+        VM_PANIC_EX("unsupported address size %d\n", decode->addressing_size);
+        break;
+    }
+}
+
+static void decode_prefix(CPUX86State *env, struct x86_decode *decode)
+{
+    while (1) {
+        /*
+         * REX prefix must come after legacy prefixes.
+         * REX before legacy is ignored.
+         * Clear rex to simulate this.
+         */
+        uint8_t byte = decode_byte(env, decode);
+        switch (byte) {
+        case PREFIX_LOCK:
+            decode->lock = byte;
+            decode->rex.rex = 0;
+            break;
+        case PREFIX_REPN:
+        case PREFIX_REP:
+            decode->rep = byte;
+            decode->rex.rex = 0;
+            break;
+        case PREFIX_CS_SEG_OVERRIDE:
+        case PREFIX_SS_SEG_OVERRIDE:
+        case PREFIX_DS_SEG_OVERRIDE:
+        case PREFIX_ES_SEG_OVERRIDE:
+        case PREFIX_FS_SEG_OVERRIDE:
+        case PREFIX_GS_SEG_OVERRIDE:
+            decode->segment_override = byte;
+            decode->rex.rex = 0;
+            break;
+        case PREFIX_OP_SIZE_OVERRIDE:
+            decode->op_size_override = byte;
+            decode->rex.rex = 0;
+            break;
+        case PREFIX_ADDR_SIZE_OVERRIDE:
+            decode->addr_size_override = byte;
+            decode->rex.rex = 0;
+            break;
+        case PREFIX_REX ... (PREFIX_REX + 0xf):
+            if (x86_is_long_mode(env_cpu(env))) {
+                decode->rex.rex = byte;
+                break;
+            }
+            /* fall through when not in long mode */
+        default:
+            decode->len--;
+            return;
+        }
+    }
+}
+
+void set_addressing_size(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->addressing_size = -1;
+    if (x86_is_real(env_cpu(env)) || x86_is_v8086(env_cpu(env))) {
+        if (decode->addr_size_override) {
+            decode->addressing_size = 4;
+        } else {
+            decode->addressing_size = 2;
+        }
+    } else if (!x86_is_long_mode(env_cpu(env))) {
+        /* protected */
+        x86_segment_descriptor cs;
+        emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS);
+        /* check db */
+        if (cs.db) {
+            if (decode->addr_size_override) {
+                decode->addressing_size = 2;
+            } else {
+                decode->addressing_size = 4;
+            }
+        } else {
+            if (decode->addr_size_override) {
+                decode->addressing_size = 4;
+            } else {
+                decode->addressing_size = 2;
+            }
+        }
+    } else {
+        /* long */
+        if (decode->addr_size_override) {
+            decode->addressing_size = 4;
+        } else {
+            decode->addressing_size = 8;
+        }
+    }
+}
+
+void set_operand_size(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->operand_size = -1;
+    if (x86_is_real(env_cpu(env)) || x86_is_v8086(env_cpu(env))) {
+        if (decode->op_size_override) {
+            decode->operand_size = 4;
+        } else {
+            decode->operand_size = 2;
+        }
+    } else if (!x86_is_long_mode(env_cpu(env))) {
+        /* protected */
+        x86_segment_descriptor cs;
+        emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS);
+        /* check db */
+        if (cs.db) {
+            if (decode->op_size_override) {
+                decode->operand_size = 2;
+            } else{
+                decode->operand_size = 4;
+            }
+        } else {
+            if (decode->op_size_override) {
+                decode->operand_size = 4;
+            } else {
+                decode->operand_size = 2;
+            }
+        }
+    } else {
+        /* long */
+        if (decode->op_size_override) {
+            decode->operand_size = 2;
+        } else {
+            decode->operand_size = 4;
+        }
+
+        if (decode->rex.w) {
+            decode->operand_size = 8;
+        }
+    }
+}
+
+static void decode_sib(CPUX86State *env, struct x86_decode *decode)
+{
+    if ((decode->modrm.mod != 3) && (4 == decode->modrm.rm) &&
+        (decode->addressing_size != 2)) {
+        decode->sib.sib = decode_byte(env, decode);
+        decode->sib_present = true;
+    }
+}
+
+/* 16 bit modrm */
+int disp16_tbl[4][8] = {
+    {0, 0, 0, 0, 0, 0, 2, 0},
+    {1, 1, 1, 1, 1, 1, 1, 1},
+    {2, 2, 2, 2, 2, 2, 2, 2},
+    {0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+/* 32/64-bit modrm */
+int disp32_tbl[4][8] = {
+    {0, 0, 0, 0, -1, 4, 0, 0},
+    {1, 1, 1, 1, 1, 1, 1, 1},
+    {4, 4, 4, 4, 4, 4, 4, 4},
+    {0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+static inline void decode_displacement(CPUX86State *env, struct x86_decode *decode)
+{
+    int addressing_size = decode->addressing_size;
+    int mod = decode->modrm.mod;
+    int rm = decode->modrm.rm;
+    
+    decode->displacement_size = 0;
+    switch (addressing_size) {
+    case 2:
+        decode->displacement_size = disp16_tbl[mod][rm];
+        if (decode->displacement_size) {
+            decode->displacement = (uint16_t)decode_bytes(env, decode,
+                                    decode->displacement_size);
+        }
+        break;
+    case 4:
+    case 8:
+        if (-1 == disp32_tbl[mod][rm]) {
+            if (5 == decode->sib.base) {
+                decode->displacement_size = 4;
+            }
+        } else {
+            decode->displacement_size = disp32_tbl[mod][rm];
+        }
+
+        if (decode->displacement_size) {
+            decode->displacement = (uint32_t)decode_bytes(env, decode,
+                                                decode->displacement_size);
+        }
+        break;
+    }
+}
+
+static inline void decode_modrm(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->modrm.modrm = decode_byte(env, decode);
+    decode->is_modrm = true;
+
+    decode_sib(env, decode);
+    decode_displacement(env, decode);
+}
+
+static inline void decode_opcode_general(CPUX86State *env,
+                                         struct x86_decode *decode,
+                                         uint8_t opcode,
+                                         struct decode_tbl *inst_decoder)
+{
+    decode->cmd = inst_decoder->cmd;
+    if (inst_decoder->operand_size) {
+        decode->operand_size = inst_decoder->operand_size;
+    }
+    decode->flags_mask = inst_decoder->flags_mask;
+
+    if (inst_decoder->is_modrm) {
+        decode_modrm(env, decode);
+    }
+    if (inst_decoder->decode_op1) {
+        inst_decoder->decode_op1(env, decode, &decode->op[0]);
+    }
+    if (inst_decoder->decode_op2) {
+        inst_decoder->decode_op2(env, decode, &decode->op[1]);
+    }
+    if (inst_decoder->decode_op3) {
+        inst_decoder->decode_op3(env, decode, &decode->op[2]);
+    }
+    if (inst_decoder->decode_op4) {
+        inst_decoder->decode_op4(env, decode, &decode->op[3]);
+    }
+    if (inst_decoder->decode_postfix) {
+        inst_decoder->decode_postfix(env, decode);
+    }
+}
+
+static inline void decode_opcode_1(CPUX86State *env, struct x86_decode *decode,
+                                   uint8_t opcode)
+{
+    struct decode_tbl *inst_decoder = &_decode_tbl1[opcode];
+    decode_opcode_general(env, decode, opcode, inst_decoder);
+}
+
+
+static inline void decode_opcode_2(CPUX86State *env, struct x86_decode *decode,
+                                   uint8_t opcode)
+{
+    struct decode_tbl *inst_decoder = &_decode_tbl2[opcode];
+    decode_opcode_general(env, decode, opcode, inst_decoder);
+}
+
+static void decode_opcodes(CPUX86State *env, struct x86_decode *decode)
+{
+    uint8_t opcode;
+
+    opcode = decode_byte(env, decode);
+    decode->opcode[decode->opcode_len++] = opcode;
+    if (opcode != OPCODE_ESCAPE) {
+        decode_opcode_1(env, decode, opcode);
+    } else {
+        opcode = decode_byte(env, decode);
+        decode->opcode[decode->opcode_len++] = opcode;
+        decode_opcode_2(env, decode, opcode);
+    }
+}
+
+uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode)
+{
+    memset(decode, 0, sizeof(*decode));
+    decode_prefix(env, decode);
+    set_addressing_size(env, decode);
+    set_operand_size(env, decode);
+
+    decode_opcodes(env, decode);
+
+    return decode->len;
+}
+
+void init_decoder(void)
+{
+    int i;
+    
+    for (i = 0; i < ARRAY_SIZE(_decode_tbl1); i++) {
+        memcpy(&_decode_tbl1[i], &invl_inst, sizeof(invl_inst));
+    }
+    for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) {
+        memcpy(&_decode_tbl2[i], &invl_inst, sizeof(invl_inst));
+    }
+    for (i = 0; i < ARRAY_SIZE(_decode_tbl3); i++) {
+        memcpy(&_decode_tbl3[i], &invl_inst_x87, sizeof(invl_inst_x87));
+    
+    }
+    for (i = 0; i < ARRAY_SIZE(_1op_inst); i++) {
+        _decode_tbl1[_1op_inst[i].opcode] = _1op_inst[i];
+    }
+    for (i = 0; i < ARRAY_SIZE(_2op_inst); i++) {
+        _decode_tbl2[_2op_inst[i].opcode] = _2op_inst[i];
+    }
+    for (i = 0; i < ARRAY_SIZE(_x87_inst); i++) {
+        int index = ((_x87_inst[i].opcode & 0xf) << 4) |
+                    ((_x87_inst[i].modrm_mod & 1) << 3) |
+                    _x87_inst[i].modrm_reg;
+        _decode_tbl3[index] = _x87_inst[i];
+    }
+}
+
+
+const char *decode_cmd_to_string(enum x86_decode_cmd cmd)
+{
+    static const char *cmds[] = {"INVL", "PUSH", "PUSH_SEG", "POP", "POP_SEG",
+        "MOV", "MOVSX", "MOVZX", "CALL_NEAR", "CALL_NEAR_ABS_INDIRECT",
+        "CALL_FAR_ABS_INDIRECT", "CMD_CALL_FAR", "RET_NEAR", "RET_FAR", "ADD",
+        "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP", "INC", "DEC", "TST",
+        "NOT", "NEG", "JMP_NEAR", "JMP_NEAR_ABS_INDIRECT", "JMP_FAR",
+        "JMP_FAR_ABS_INDIRECT", "LEA", "JXX", "JCXZ", "SETXX", "MOV_TO_SEG",
+        "MOV_FROM_SEG", "CLI", "STI", "CLD", "STD", "STC", "CLC", "OUT", "IN",
+        "INS", "OUTS", "LIDT", "SIDT", "LGDT", "SGDT", "SMSW", "LMSW",
+        "RDTSCP", "INVLPG", "MOV_TO_CR", "MOV_FROM_CR", "MOV_TO_DR",
+        "MOV_FROM_DR", "PUSHF", "POPF", "CPUID", "ROL", "ROR", "RCL", "RCR",
+        "SHL", "SAL", "SHR", "SHRD", "SHLD", "SAR", "DIV", "IDIV", "MUL",
+        "IMUL_3", "IMUL_2", "IMUL_1", "MOVS", "CMPS", "SCAS", "LODS", "STOS",
+        "BSWAP", "XCHG", "RDTSC", "RDMSR", "WRMSR", "ENTER", "LEAVE", "BT",
+        "BTS", "BTC", "BTR", "BSF", "BSR", "IRET", "INT", "POPA", "PUSHA",
+        "CWD", "CBW", "DAS", "AAD", "AAM", "AAS", "LOOP", "SLDT", "STR", "LLDT",
+        "LTR", "VERR", "VERW", "SAHF", "LAHF", "WBINVD", "LDS", "LSS", "LES",
+        "LGS", "LFS", "CMC", "XLAT", "NOP", "CMOV", "CLTS", "XADD", "HLT",
+        "CMPXCHG8B", "CMPXCHG", "POPCNT", "FNINIT", "FLD", "FLDxx", "FNSTCW",
+        "FNSTSW", "FNSETPM", "FSAVE", "FRSTOR", "FXSAVE", "FXRSTOR", "FDIV",
+        "FMUL", "FSUB", "FADD", "EMMS", "MFENCE", "SFENCE", "LFENCE",
+        "PREFETCH", "FST", "FABS", "FUCOM", "FUCOMI", "FLDCW",
+        "FXCH", "FCHS", "FCMOV", "FRNDINT", "FXAM", "LAST"};
+    return cmds[cmd];
+}
+
+target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode,
+                               target_ulong addr, X86Seg seg)
+{
+    switch (decode->segment_override) {
+    case PREFIX_CS_SEG_OVERRIDE:
+        seg = R_CS;
+        break;
+    case PREFIX_SS_SEG_OVERRIDE:
+        seg = R_SS;
+        break;
+    case PREFIX_DS_SEG_OVERRIDE:
+        seg = R_DS;
+        break;
+    case PREFIX_ES_SEG_OVERRIDE:
+        seg = R_ES;
+        break;
+    case PREFIX_FS_SEG_OVERRIDE:
+        seg = R_FS;
+        break;
+    case PREFIX_GS_SEG_OVERRIDE:
+        seg = R_GS;
+        break;
+    default:
+        break;
+    }
+    return linear_addr_size(env_cpu(env), addr, decode->addressing_size, seg);
+}
diff --git a/target/i386/emulate/x86_decode.h b/target/i386/emulate/x86_decode.h
new file mode 100644 (file)
index 0000000..930d965
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2016 Veertu Inc,
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef X86_EMU_DECODE_H
+#define X86_EMU_DECODE_H
+
+#include "cpu.h"
+#include "x86.h"
+
+typedef enum x86_prefix {
+    /* group 1 */
+    PREFIX_LOCK =                  0xf0,
+    PREFIX_REPN =                  0xf2,
+    PREFIX_REP =                   0xf3,
+    /* group 2 */
+    PREFIX_CS_SEG_OVERRIDE =       0x2e,
+    PREFIX_SS_SEG_OVERRIDE =       0x36,
+    PREFIX_DS_SEG_OVERRIDE =       0x3e,
+    PREFIX_ES_SEG_OVERRIDE =       0x26,
+    PREFIX_FS_SEG_OVERRIDE =       0x64,
+    PREFIX_GS_SEG_OVERRIDE =       0x65,
+    /* group 3 */
+    PREFIX_OP_SIZE_OVERRIDE =      0x66,
+    /* group 4 */
+    PREFIX_ADDR_SIZE_OVERRIDE =    0x67,
+
+    PREFIX_REX                   = 0x40,
+} x86_prefix;
+
+enum x86_decode_cmd {
+    X86_DECODE_CMD_INVL = 0,
+    
+    X86_DECODE_CMD_PUSH,
+    X86_DECODE_CMD_PUSH_SEG,
+    X86_DECODE_CMD_POP,
+    X86_DECODE_CMD_POP_SEG,
+    X86_DECODE_CMD_MOV,
+    X86_DECODE_CMD_MOVSX,
+    X86_DECODE_CMD_MOVZX,
+    X86_DECODE_CMD_CALL_NEAR,
+    X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT,
+    X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT,
+    X86_DECODE_CMD_CALL_FAR,
+    X86_DECODE_RET_NEAR,
+    X86_DECODE_RET_FAR,
+    X86_DECODE_CMD_ADD,
+    X86_DECODE_CMD_OR,
+    X86_DECODE_CMD_ADC,
+    X86_DECODE_CMD_SBB,
+    X86_DECODE_CMD_AND,
+    X86_DECODE_CMD_SUB,
+    X86_DECODE_CMD_XOR,
+    X86_DECODE_CMD_CMP,
+    X86_DECODE_CMD_INC,
+    X86_DECODE_CMD_DEC,
+    X86_DECODE_CMD_TST,
+    X86_DECODE_CMD_NOT,
+    X86_DECODE_CMD_NEG,
+    X86_DECODE_CMD_JMP_NEAR,
+    X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT,
+    X86_DECODE_CMD_JMP_FAR,
+    X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT,
+    X86_DECODE_CMD_LEA,
+    X86_DECODE_CMD_JXX,
+    X86_DECODE_CMD_JCXZ,
+    X86_DECODE_CMD_SETXX,
+    X86_DECODE_CMD_MOV_TO_SEG,
+    X86_DECODE_CMD_MOV_FROM_SEG,
+    X86_DECODE_CMD_CLI,
+    X86_DECODE_CMD_STI,
+    X86_DECODE_CMD_CLD,
+    X86_DECODE_CMD_STD,
+    X86_DECODE_CMD_STC,
+    X86_DECODE_CMD_CLC,
+    X86_DECODE_CMD_OUT,
+    X86_DECODE_CMD_IN,
+    X86_DECODE_CMD_INS,
+    X86_DECODE_CMD_OUTS,
+    X86_DECODE_CMD_LIDT,
+    X86_DECODE_CMD_SIDT,
+    X86_DECODE_CMD_LGDT,
+    X86_DECODE_CMD_SGDT,
+    X86_DECODE_CMD_SMSW,
+    X86_DECODE_CMD_LMSW,
+    X86_DECODE_CMD_RDTSCP,
+    X86_DECODE_CMD_INVLPG,
+    X86_DECODE_CMD_MOV_TO_CR,
+    X86_DECODE_CMD_MOV_FROM_CR,
+    X86_DECODE_CMD_MOV_TO_DR,
+    X86_DECODE_CMD_MOV_FROM_DR,
+    X86_DECODE_CMD_PUSHF,
+    X86_DECODE_CMD_POPF,
+    X86_DECODE_CMD_CPUID,
+    X86_DECODE_CMD_ROL,
+    X86_DECODE_CMD_ROR,
+    X86_DECODE_CMD_RCL,
+    X86_DECODE_CMD_RCR,
+    X86_DECODE_CMD_SHL,
+    X86_DECODE_CMD_SAL,
+    X86_DECODE_CMD_SHR,
+    X86_DECODE_CMD_SHRD,
+    X86_DECODE_CMD_SHLD,
+    X86_DECODE_CMD_SAR,
+    X86_DECODE_CMD_DIV,
+    X86_DECODE_CMD_IDIV,
+    X86_DECODE_CMD_MUL,
+    X86_DECODE_CMD_IMUL_3,
+    X86_DECODE_CMD_IMUL_2,
+    X86_DECODE_CMD_IMUL_1,
+    X86_DECODE_CMD_MOVS,
+    X86_DECODE_CMD_CMPS,
+    X86_DECODE_CMD_SCAS,
+    X86_DECODE_CMD_LODS,
+    X86_DECODE_CMD_STOS,
+    X86_DECODE_CMD_BSWAP,
+    X86_DECODE_CMD_XCHG,
+    X86_DECODE_CMD_RDTSC,
+    X86_DECODE_CMD_RDMSR,
+    X86_DECODE_CMD_WRMSR,
+    X86_DECODE_CMD_ENTER,
+    X86_DECODE_CMD_LEAVE,
+    X86_DECODE_CMD_BT,
+    X86_DECODE_CMD_BTS,
+    X86_DECODE_CMD_BTC,
+    X86_DECODE_CMD_BTR,
+    X86_DECODE_CMD_BSF,
+    X86_DECODE_CMD_BSR,
+    X86_DECODE_CMD_IRET,
+    X86_DECODE_CMD_INT,
+    X86_DECODE_CMD_POPA,
+    X86_DECODE_CMD_PUSHA,
+    X86_DECODE_CMD_CWD,
+    X86_DECODE_CMD_CBW,
+    X86_DECODE_CMD_DAS,
+    X86_DECODE_CMD_AAD,
+    X86_DECODE_CMD_AAM,
+    X86_DECODE_CMD_AAS,
+    X86_DECODE_CMD_LOOP,
+    X86_DECODE_CMD_SLDT,
+    X86_DECODE_CMD_STR,
+    X86_DECODE_CMD_LLDT,
+    X86_DECODE_CMD_LTR,
+    X86_DECODE_CMD_VERR,
+    X86_DECODE_CMD_VERW,
+    X86_DECODE_CMD_SAHF,
+    X86_DECODE_CMD_LAHF,
+    X86_DECODE_CMD_WBINVD,
+    X86_DECODE_CMD_LDS,
+    X86_DECODE_CMD_LSS,
+    X86_DECODE_CMD_LES,
+    X86_DECODE_XMD_LGS,
+    X86_DECODE_CMD_LFS,
+    X86_DECODE_CMD_CMC,
+    X86_DECODE_CMD_XLAT,
+    X86_DECODE_CMD_NOP,
+    X86_DECODE_CMD_CMOV,
+    X86_DECODE_CMD_CLTS,
+    X86_DECODE_CMD_XADD,
+    X86_DECODE_CMD_HLT,
+    X86_DECODE_CMD_CMPXCHG8B,
+    X86_DECODE_CMD_CMPXCHG,
+    X86_DECODE_CMD_POPCNT,
+    
+    X86_DECODE_CMD_FNINIT,
+    X86_DECODE_CMD_FLD,
+    X86_DECODE_CMD_FLDxx,
+    X86_DECODE_CMD_FNSTCW,
+    X86_DECODE_CMD_FNSTSW,
+    X86_DECODE_CMD_FNSETPM,
+    X86_DECODE_CMD_FSAVE,
+    X86_DECODE_CMD_FRSTOR,
+    X86_DECODE_CMD_FXSAVE,
+    X86_DECODE_CMD_FXRSTOR,
+    X86_DECODE_CMD_FDIV,
+    X86_DECODE_CMD_FMUL,
+    X86_DECODE_CMD_FSUB,
+    X86_DECODE_CMD_FADD,
+    X86_DECODE_CMD_EMMS,
+    X86_DECODE_CMD_MFENCE,
+    X86_DECODE_CMD_SFENCE,
+    X86_DECODE_CMD_LFENCE,
+    X86_DECODE_CMD_PREFETCH,
+    X86_DECODE_CMD_CLFLUSH,
+    X86_DECODE_CMD_FST,
+    X86_DECODE_CMD_FABS,
+    X86_DECODE_CMD_FUCOM,
+    X86_DECODE_CMD_FUCOMI,
+    X86_DECODE_CMD_FLDCW,
+    X86_DECODE_CMD_FXCH,
+    X86_DECODE_CMD_FCHS,
+    X86_DECODE_CMD_FCMOV,
+    X86_DECODE_CMD_FRNDINT,
+    X86_DECODE_CMD_FXAM,
+
+    X86_DECODE_CMD_LAST,
+};
+
+const char *decode_cmd_to_string(enum x86_decode_cmd cmd);
+
+typedef struct x86_modrm {
+    union {
+        uint8_t modrm;
+        struct {
+            uint8_t rm:3;
+            uint8_t reg:3;
+            uint8_t mod:2;
+        };
+    };
+} __attribute__ ((__packed__)) x86_modrm;
+
+typedef struct x86_sib {
+    union {
+        uint8_t sib;
+        struct {
+            uint8_t base:3;
+            uint8_t index:3;
+            uint8_t scale:2;
+        };
+    };
+} __attribute__ ((__packed__)) x86_sib;
+
+typedef struct x86_rex {
+    union {
+        uint8_t rex;
+        struct {
+            uint8_t b:1;
+            uint8_t x:1;
+            uint8_t r:1;
+            uint8_t w:1;
+            uint8_t unused:4;
+        };
+    };
+} __attribute__ ((__packed__)) x86_rex;
+
+typedef enum x86_var_type {
+    X86_VAR_IMMEDIATE,
+    X86_VAR_OFFSET,
+    X86_VAR_REG,
+    X86_VAR_RM,
+
+    /* for floating point computations */
+    X87_VAR_REG,
+    X87_VAR_FLOATP,
+    X87_VAR_INTP,
+    X87_VAR_BYTEP,
+} x86_var_type;
+
+typedef struct x86_decode_op {
+    enum x86_var_type type;
+    int size;
+
+    int reg;
+    target_ulong val;
+
+    target_ulong ptr;
+} x86_decode_op;
+
+typedef struct x86_decode {
+    int len;
+    uint8_t opcode[4];
+    uint8_t opcode_len;
+    enum x86_decode_cmd cmd;
+    int addressing_size;
+    int operand_size;
+    int lock;
+    int rep;
+    int op_size_override;
+    int addr_size_override;
+    int segment_override;
+    int control_change_inst;
+    bool fwait;
+    bool fpop_stack;
+    bool frev;
+
+    uint32_t displacement;
+    uint8_t displacement_size;
+    struct x86_rex rex;
+    bool is_modrm;
+    bool sib_present;
+    struct x86_sib sib;
+    struct x86_modrm modrm;
+    struct x86_decode_op op[4];
+    bool is_fpu;
+    uint32_t flags_mask;
+
+} x86_decode;
+
+uint64_t sign(uint64_t val, int size);
+
+uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode);
+
+target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present,
+                         int is_extended, int size);
+target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present,
+                         int is_extended, int size);
+void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,
+                        struct x86_decode_op *op);
+target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode,
+                               target_ulong addr, enum X86Seg seg);
+
+void init_decoder(void);
+void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode,
+                          struct x86_decode_op *op);
+void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode,
+                          struct x86_decode_op *op);
+void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode,
+                          struct x86_decode_op *op);
+void set_addressing_size(CPUX86State *env, struct x86_decode *decode);
+void set_operand_size(CPUX86State *env, struct x86_decode *decode);
+
+#endif
diff --git a/target/i386/emulate/x86_emu.c b/target/i386/emulate/x86_emu.c
new file mode 100644 (file)
index 0000000..26a4876
--- /dev/null
@@ -0,0 +1,1259 @@
+/*
+ * Copyright (C) 2016 Veertu Inc,
+ * Copyright (C) 2017 Google Inc,
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/////////////////////////////////////////////////////////////////////////
+//
+//  Copyright (C) 2001-2012  The Bochs Project
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
+/////////////////////////////////////////////////////////////////////////
+
+#include "qemu/osdep.h"
+#include "panic.h"
+#include "x86_decode.h"
+#include "x86.h"
+#include "x86_emu.h"
+#include "x86_flags.h"
+
+#define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \
+{                                                       \
+    fetch_operands(env, decode, 2, true, true, false);  \
+    switch (decode->operand_size) {                     \
+    case 1:                                         \
+    {                                               \
+        uint8_t v1 = (uint8_t)decode->op[0].val;    \
+        uint8_t v2 = (uint8_t)decode->op[1].val;    \
+        uint8_t diff = v1 cmd v2;                   \
+        if (save_res) {                              \
+            write_val_ext(env, decode->op[0].ptr, diff, 1);  \
+        } \
+        FLAGS_FUNC##8(env, v1, v2, diff);           \
+        break;                                      \
+    }                                               \
+    case 2:                                        \
+    {                                               \
+        uint16_t v1 = (uint16_t)decode->op[0].val;  \
+        uint16_t v2 = (uint16_t)decode->op[1].val;  \
+        uint16_t diff = v1 cmd v2;                  \
+        if (save_res) {                              \
+            write_val_ext(env, decode->op[0].ptr, diff, 2); \
+        } \
+        FLAGS_FUNC##16(env, v1, v2, diff);          \
+        break;                                      \
+    }                                               \
+    case 4:                                        \
+    {                                               \
+        uint32_t v1 = (uint32_t)decode->op[0].val;  \
+        uint32_t v2 = (uint32_t)decode->op[1].val;  \
+        uint32_t diff = v1 cmd v2;                  \
+        if (save_res) {                              \
+            write_val_ext(env, decode->op[0].ptr, diff, 4); \
+        } \
+        FLAGS_FUNC##32(env, v1, v2, diff);          \
+        break;                                      \
+    }                                               \
+    default:                                        \
+        VM_PANIC("bad size\n");                    \
+    }                                                   \
+}                                                       \
+
+target_ulong read_reg(CPUX86State *env, int reg, int size)
+{
+    switch (size) {
+    case 1:
+        return x86_reg(env, reg)->lx;
+    case 2:
+        return x86_reg(env, reg)->rx;
+    case 4:
+        return x86_reg(env, reg)->erx;
+    case 8:
+        return x86_reg(env, reg)->rrx;
+    default:
+        abort();
+    }
+    return 0;
+}
+
+void write_reg(CPUX86State *env, int reg, target_ulong val, int size)
+{
+    switch (size) {
+    case 1:
+        x86_reg(env, reg)->lx = val;
+        break;
+    case 2:
+        x86_reg(env, reg)->rx = val;
+        break;
+    case 4:
+        x86_reg(env, reg)->rrx = (uint32_t)val;
+        break;
+    case 8:
+        x86_reg(env, reg)->rrx = val;
+        break;
+    default:
+        abort();
+    }
+}
+
+target_ulong read_val_from_reg(target_ulong reg_ptr, int size)
+{
+    target_ulong val;
+    
+    switch (size) {
+    case 1:
+        val = *(uint8_t *)reg_ptr;
+        break;
+    case 2:
+        val = *(uint16_t *)reg_ptr;
+        break;
+    case 4:
+        val = *(uint32_t *)reg_ptr;
+        break;
+    case 8:
+        val = *(uint64_t *)reg_ptr;
+        break;
+    default:
+        abort();
+    }
+    return val;
+}
+
+void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size)
+{
+    switch (size) {
+    case 1:
+        *(uint8_t *)reg_ptr = val;
+        break;
+    case 2:
+        *(uint16_t *)reg_ptr = val;
+        break;
+    case 4:
+        *(uint64_t *)reg_ptr = (uint32_t)val;
+        break;
+    case 8:
+        *(uint64_t *)reg_ptr = val;
+        break;
+    default:
+        abort();
+    }
+}
+
+static bool is_host_reg(CPUX86State *env, target_ulong ptr)
+{
+    return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs);
+}
+
+void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
+{
+    if (is_host_reg(env, ptr)) {
+        write_val_to_reg(ptr, val, size);
+        return;
+    }
+    emul_ops->write_mem(env_cpu(env), &val, ptr, size);
+}
+
+uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
+{
+    emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
+    return env->emu_mmio_buf;
+}
+
+
+target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size)
+{
+    target_ulong val;
+    uint8_t *mmio_ptr;
+
+    if (is_host_reg(env, ptr)) {
+        return read_val_from_reg(ptr, size);
+    }
+
+    mmio_ptr = read_mmio(env, ptr, size);
+    switch (size) {
+    case 1:
+        val = *(uint8_t *)mmio_ptr;
+        break;
+    case 2:
+        val = *(uint16_t *)mmio_ptr;
+        break;
+    case 4:
+        val = *(uint32_t *)mmio_ptr;
+        break;
+    case 8:
+        val = *(uint64_t *)mmio_ptr;
+        break;
+    default:
+        VM_PANIC("bad size\n");
+        break;
+    }
+    return val;
+}
+
+static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
+                           int n, bool val_op0, bool val_op1, bool val_op2)
+{
+    int i;
+    bool calc_val[3] = {val_op0, val_op1, val_op2};
+
+    for (i = 0; i < n; i++) {
+        switch (decode->op[i].type) {
+        case X86_VAR_IMMEDIATE:
+            break;
+        case X86_VAR_REG:
+            VM_PANIC_ON(!decode->op[i].ptr);
+            if (calc_val[i]) {
+                decode->op[i].val = read_val_from_reg(decode->op[i].ptr,
+                                                      decode->operand_size);
+            }
+            break;
+        case X86_VAR_RM:
+            calc_modrm_operand(env, decode, &decode->op[i]);
+            if (calc_val[i]) {
+                decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
+                                                 decode->operand_size);
+            }
+            break;
+        case X86_VAR_OFFSET:
+            decode->op[i].ptr = decode_linear_addr(env, decode,
+                                                   decode->op[i].ptr,
+                                                   R_DS);
+            if (calc_val[i]) {
+                decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
+                                                 decode->operand_size);
+            }
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+static void exec_mov(CPUX86State *env, struct x86_decode *decode)
+{
+    fetch_operands(env, decode, 2, false, true, false);
+    write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
+                  decode->operand_size);
+
+    env->eip += decode->len;
+}
+
+static void exec_add(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
+    env->eip += decode->len;
+}
+
+static void exec_or(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true);
+    env->eip += decode->len;
+}
+
+static void exec_adc(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true);
+    env->eip += decode->len;
+}
+
+static void exec_sbb(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true);
+    env->eip += decode->len;
+}
+
+static void exec_and(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true);
+    env->eip += decode->len;
+}
+
+static void exec_sub(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true);
+    env->eip += decode->len;
+}
+
+static void exec_xor(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true);
+    env->eip += decode->len;
+}
+
+static void exec_neg(CPUX86State *env, struct x86_decode *decode)
+{
+    /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/
+    int32_t val;
+    fetch_operands(env, decode, 2, true, true, false);
+
+    val = 0 - sign(decode->op[1].val, decode->operand_size);
+    write_val_ext(env, decode->op[1].ptr, val, decode->operand_size);
+
+    if (4 == decode->operand_size) {
+        SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val);
+    } else if (2 == decode->operand_size) {
+        SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val);
+    } else if (1 == decode->operand_size) {
+        SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val);
+    } else {
+        VM_PANIC("bad op size\n");
+    }
+
+    /*lflags_to_rflags(env);*/
+    env->eip += decode->len;
+}
+
+static void exec_cmp(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
+    env->eip += decode->len;
+}
+
+static void exec_inc(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[1].type = X86_VAR_IMMEDIATE;
+    decode->op[1].val = 0;
+
+    EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true);
+
+    env->eip += decode->len;
+}
+
+static void exec_dec(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[1].type = X86_VAR_IMMEDIATE;
+    decode->op[1].val = 0;
+
+    EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true);
+    env->eip += decode->len;
+}
+
+static void exec_tst(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false);
+    env->eip += decode->len;
+}
+
+static void exec_not(CPUX86State *env, struct x86_decode *decode)
+{
+    fetch_operands(env, decode, 1, true, false, false);
+
+    write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val,
+                  decode->operand_size);
+    env->eip += decode->len;
+}
+
+void exec_movzx(CPUX86State *env, struct x86_decode *decode)
+{
+    int src_op_size;
+    int op_size = decode->operand_size;
+
+    fetch_operands(env, decode, 1, false, false, false);
+
+    if (0xb6 == decode->opcode[1]) {
+        src_op_size = 1;
+    } else {
+        src_op_size = 2;
+    }
+    decode->operand_size = src_op_size;
+    calc_modrm_operand(env, decode, &decode->op[1]);
+    decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size);
+    write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
+
+    env->eip += decode->len;
+}
+
+static void exec_out(CPUX86State *env, struct x86_decode *decode)
+{
+    switch (decode->opcode[0]) {
+    case 0xe6:
+        emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1);
+        break;
+    case 0xe7:
+        emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1,
+                            decode->operand_size, 1);
+        break;
+    case 0xee:
+        emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1);
+        break;
+    case 0xef:
+        emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1,
+                            decode->operand_size, 1);
+        break;
+    default:
+        VM_PANIC("Bad out opcode\n");
+        break;
+    }
+    env->eip += decode->len;
+}
+
+static void exec_in(CPUX86State *env, struct x86_decode *decode)
+{
+    target_ulong val = 0;
+    switch (decode->opcode[0]) {
+    case 0xe4:
+        emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1);
+        break;
+    case 0xe5:
+        emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0,
+                      decode->operand_size, 1);
+        if (decode->operand_size == 2) {
+            AX(env) = val;
+        } else {
+            RAX(env) = (uint32_t)val;
+        }
+        break;
+    case 0xec:
+        emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1);
+        break;
+    case 0xed:
+        emul_ops->handle_io(env_cpu(env), DX(env), &val, 0,
+                            decode->operand_size, 1);
+        if (decode->operand_size == 2) {
+            AX(env) = val;
+        } else {
+            RAX(env) = (uint32_t)val;
+        }
+
+        break;
+    default:
+        VM_PANIC("Bad in opcode\n");
+        break;
+    }
+
+    env->eip += decode->len;
+}
+
+static inline void string_increment_reg(CPUX86State *env, int reg,
+                                        struct x86_decode *decode)
+{
+    target_ulong val = read_reg(env, reg, decode->addressing_size);
+    if (env->eflags & DF_MASK) {
+        val -= decode->operand_size;
+    } else {
+        val += decode->operand_size;
+    }
+    write_reg(env, reg, val, decode->addressing_size);
+}
+
+static inline void string_rep(CPUX86State *env, struct x86_decode *decode,
+                              void (*func)(CPUX86State *env,
+                                           struct x86_decode *ins), int rep)
+{
+    target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size);
+    while (rcx--) {
+        func(env, decode);
+        write_reg(env, R_ECX, rcx, decode->addressing_size);
+        if ((PREFIX_REP == rep) && !get_ZF(env)) {
+            break;
+        }
+        if ((PREFIX_REPN == rep) && get_ZF(env)) {
+            break;
+        }
+    }
+}
+
+static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
+{
+    target_ulong addr = linear_addr_size(env_cpu(env), RDI(env),
+                                         decode->addressing_size, R_ES);
+
+    emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0,
+                        decode->operand_size, 1);
+    emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr,
+                        decode->operand_size);
+
+    string_increment_reg(env, R_EDI, decode);
+}
+
+static void exec_ins(CPUX86State *env, struct x86_decode *decode)
+{
+    if (decode->rep) {
+        string_rep(env, decode, exec_ins_single, 0);
+    } else {
+        exec_ins_single(env, decode);
+    }
+
+    env->eip += decode->len;
+}
+
+static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
+{
+    target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
+
+    emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr,
+                       decode->operand_size);
+    emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1,
+                        decode->operand_size, 1);
+
+    string_increment_reg(env, R_ESI, decode);
+}
+
+static void exec_outs(CPUX86State *env, struct x86_decode *decode)
+{
+    if (decode->rep) {
+        string_rep(env, decode, exec_outs_single, 0);
+    } else {
+        exec_outs_single(env, decode);
+    }
+
+    env->eip += decode->len;
+}
+
+static void exec_movs_single(CPUX86State *env, struct x86_decode *decode)
+{
+    target_ulong src_addr;
+    target_ulong dst_addr;
+    target_ulong val;
+
+    src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
+    dst_addr = linear_addr_size(env_cpu(env), RDI(env),
+                                decode->addressing_size, R_ES);
+
+    val = read_val_ext(env, src_addr, decode->operand_size);
+    write_val_ext(env, dst_addr, val, decode->operand_size);
+
+    string_increment_reg(env, R_ESI, decode);
+    string_increment_reg(env, R_EDI, decode);
+}
+
+static void exec_movs(CPUX86State *env, struct x86_decode *decode)
+{
+    if (decode->rep) {
+        string_rep(env, decode, exec_movs_single, 0);
+    } else {
+        exec_movs_single(env, decode);
+    }
+
+    env->eip += decode->len;
+}
+
+static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode)
+{
+    target_ulong src_addr;
+    target_ulong dst_addr;
+
+    src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
+    dst_addr = linear_addr_size(env_cpu(env), RDI(env),
+                                decode->addressing_size, R_ES);
+
+    decode->op[0].type = X86_VAR_IMMEDIATE;
+    decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size);
+    decode->op[1].type = X86_VAR_IMMEDIATE;
+    decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size);
+
+    EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
+
+    string_increment_reg(env, R_ESI, decode);
+    string_increment_reg(env, R_EDI, decode);
+}
+
+static void exec_cmps(CPUX86State *env, struct x86_decode *decode)
+{
+    if (decode->rep) {
+        string_rep(env, decode, exec_cmps_single, decode->rep);
+    } else {
+        exec_cmps_single(env, decode);
+    }
+    env->eip += decode->len;
+}
+
+
+static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
+{
+    target_ulong addr;
+    target_ulong val;
+
+    addr = linear_addr_size(env_cpu(env), RDI(env),
+                            decode->addressing_size, R_ES);
+    val = read_reg(env, R_EAX, decode->operand_size);
+    emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size);
+
+    string_increment_reg(env, R_EDI, decode);
+}
+
+
+static void exec_stos(CPUX86State *env, struct x86_decode *decode)
+{
+    if (decode->rep) {
+        string_rep(env, decode, exec_stos_single, 0);
+    } else {
+        exec_stos_single(env, decode);
+    }
+
+    env->eip += decode->len;
+}
+
+static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
+{
+    target_ulong addr;
+
+    addr = linear_addr_size(env_cpu(env), RDI(env),
+                            decode->addressing_size, R_ES);
+    decode->op[1].type = X86_VAR_IMMEDIATE;
+    emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
+
+    EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
+    string_increment_reg(env, R_EDI, decode);
+}
+
+static void exec_scas(CPUX86State *env, struct x86_decode *decode)
+{
+    decode->op[0].type = X86_VAR_REG;
+    decode->op[0].reg = R_EAX;
+    if (decode->rep) {
+        string_rep(env, decode, exec_scas_single, decode->rep);
+    } else {
+        exec_scas_single(env, decode);
+    }
+
+    env->eip += decode->len;
+}
+
+static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
+{
+    target_ulong addr;
+    target_ulong val = 0;
+
+    addr = decode_linear_addr(env, decode, RSI(env), R_DS);
+    emul_ops->read_mem(env_cpu(env), &val, addr,  decode->operand_size);
+    write_reg(env, R_EAX, val, decode->operand_size);
+
+    string_increment_reg(env, R_ESI, decode);
+}
+
+static void exec_lods(CPUX86State *env, struct x86_decode *decode)
+{
+    if (decode->rep) {
+        string_rep(env, decode, exec_lods_single, 0);
+    } else {
+        exec_lods_single(env, decode);
+    }
+
+    env->eip += decode->len;
+}
+
+void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code)
+{
+    env->exception_nr = exception_index;
+    env->error_code = error_code;
+    env->has_error_code = true;
+    env->exception_injected = 1;
+}
+
+static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode)
+{
+    emul_ops->simulate_rdmsr(env_cpu(env));
+    env->eip += decode->len;
+}
+
+static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode)
+{
+    emul_ops->simulate_wrmsr(env_cpu(env));
+    env->eip += decode->len;
+}
+
+/*
+ * flag:
+ * 0 - bt, 1 - btc, 2 - bts, 3 - btr
+ */
+static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
+{
+    int32_t displacement;
+    uint8_t index;
+    bool cf;
+    int mask = (4 == decode->operand_size) ? 0x1f : 0xf;
+
+    VM_PANIC_ON(decode->rex.rex);
+
+    fetch_operands(env, decode, 2, false, true, false);
+    index = decode->op[1].val & mask;
+
+    if (decode->op[0].type != X86_VAR_REG) {
+        if (4 == decode->operand_size) {
+            displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32;
+            decode->op[0].ptr += 4 * displacement;
+        } else if (2 == decode->operand_size) {
+            displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16;
+            decode->op[0].ptr += 2 * displacement;
+        } else {
+            VM_PANIC("bt 64bit\n");
+        }
+    }
+    decode->op[0].val = read_val_ext(env, decode->op[0].ptr,
+                                     decode->operand_size);
+    cf = (decode->op[0].val >> index) & 0x01;
+
+    switch (flag) {
+    case 0:
+        set_CF(env, cf);
+        return;
+    case 1:
+        decode->op[0].val ^= (1u << index);
+        break;
+    case 2:
+        decode->op[0].val |= (1u << index);
+        break;
+    case 3:
+        decode->op[0].val &= ~(1u << index);
+        break;
+    }
+    write_val_ext(env, decode->op[0].ptr, decode->op[0].val,
+                  decode->operand_size);
+    set_CF(env, cf);
+}
+
+static void exec_bt(CPUX86State *env, struct x86_decode *decode)
+{
+    do_bt(env, decode, 0);
+    env->eip += decode->len;
+}
+
+static void exec_btc(CPUX86State *env, struct x86_decode *decode)
+{
+    do_bt(env, decode, 1);
+    env->eip += decode->len;
+}
+
+static void exec_btr(CPUX86State *env, struct x86_decode *decode)
+{
+    do_bt(env, decode, 3);
+    env->eip += decode->len;
+}
+
+static void exec_bts(CPUX86State *env, struct x86_decode *decode)
+{
+    do_bt(env, decode, 2);
+    env->eip += decode->len;
+}
+
+void exec_shl(CPUX86State *env, struct x86_decode *decode)
+{
+    uint8_t count;
+    int of = 0, cf = 0;
+
+    fetch_operands(env, decode, 2, true, true, false);
+
+    count = decode->op[1].val;
+    count &= 0x1f;      /* count is masked to 5 bits*/
+    if (!count) {
+        goto exit;
+    }
+
+    switch (decode->operand_size) {
+    case 1:
+    {
+        uint8_t res = 0;
+        if (count <= 8) {
+            res = (decode->op[0].val << count);
+            cf = (decode->op[0].val >> (8 - count)) & 0x1;
+            of = cf ^ (res >> 7);
+        }
+
+        write_val_ext(env, decode->op[0].ptr, res, 1);
+        SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res);
+        SET_FLAGS_OxxxxC(env, of, cf);
+        break;
+    }
+    case 2:
+    {
+        uint16_t res = 0;
+
+        /* from bochs */
+        if (count <= 16) {
+            res = (decode->op[0].val << count);
+            cf = (decode->op[0].val >> (16 - count)) & 0x1;
+            of = cf ^ (res >> 15); /* of = cf ^ result15 */
+        }
+
+        write_val_ext(env, decode->op[0].ptr, res, 2);
+        SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res);
+        SET_FLAGS_OxxxxC(env, of, cf);
+        break;
+    }
+    case 4:
+    {
+        uint32_t res = decode->op[0].val << count;
+
+        write_val_ext(env, decode->op[0].ptr, res, 4);
+        SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res);
+        cf = (decode->op[0].val >> (32 - count)) & 0x1;
+        of = cf ^ (res >> 31); /* of = cf ^ result31 */
+        SET_FLAGS_OxxxxC(env, of, cf);
+        break;
+    }
+    default:
+        abort();
+    }
+
+exit:
+    /* lflags_to_rflags(env); */
+    env->eip += decode->len;
+}
+
+void exec_movsx(CPUX86State *env, struct x86_decode *decode)
+{
+    int src_op_size;
+    int op_size = decode->operand_size;
+
+    fetch_operands(env, decode, 2, false, false, false);
+
+    if (0xbe == decode->opcode[1]) {
+        src_op_size = 1;
+    } else {
+        src_op_size = 2;
+    }
+
+    decode->operand_size = src_op_size;
+    calc_modrm_operand(env, decode, &decode->op[1]);
+    decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size),
+                             src_op_size);
+
+    write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
+
+    env->eip += decode->len;
+}
+
+void exec_ror(CPUX86State *env, struct x86_decode *decode)
+{
+    uint8_t count;
+
+    fetch_operands(env, decode, 2, true, true, false);
+    count = decode->op[1].val;
+
+    switch (decode->operand_size) {
+    case 1:
+    {
+        uint32_t bit6, bit7;
+        uint8_t res;
+
+        if ((count & 0x07) == 0) {
+            if (count & 0x18) {
+                bit6 = ((uint8_t)decode->op[0].val >> 6) & 1;
+                bit7 = ((uint8_t)decode->op[0].val >> 7) & 1;
+                SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
+             }
+        } else {
+            count &= 0x7; /* use only bottom 3 bits */
+            res = ((uint8_t)decode->op[0].val >> count) |
+                   ((uint8_t)decode->op[0].val << (8 - count));
+            write_val_ext(env, decode->op[0].ptr, res, 1);
+            bit6 = (res >> 6) & 1;
+            bit7 = (res >> 7) & 1;
+            /* set eflags: ROR count affects the following flags: C, O */
+            SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
+        }
+        break;
+    }
+    case 2:
+    {
+        uint32_t bit14, bit15;
+        uint16_t res;
+
+        if ((count & 0x0f) == 0) {
+            if (count & 0x10) {
+                bit14 = ((uint16_t)decode->op[0].val >> 14) & 1;
+                bit15 = ((uint16_t)decode->op[0].val >> 15) & 1;
+                /* of = result14 ^ result15 */
+                SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
+            }
+        } else {
+            count &= 0x0f;  /* use only 4 LSB's */
+            res = ((uint16_t)decode->op[0].val >> count) |
+                   ((uint16_t)decode->op[0].val << (16 - count));
+            write_val_ext(env, decode->op[0].ptr, res, 2);
+
+            bit14 = (res >> 14) & 1;
+            bit15 = (res >> 15) & 1;
+            /* of = result14 ^ result15 */
+            SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
+        }
+        break;
+    }
+    case 4:
+    {
+        uint32_t bit31, bit30;
+        uint32_t res;
+
+        count &= 0x1f;
+        if (count) {
+            res = ((uint32_t)decode->op[0].val >> count) |
+                   ((uint32_t)decode->op[0].val << (32 - count));
+            write_val_ext(env, decode->op[0].ptr, res, 4);
+
+            bit31 = (res >> 31) & 1;
+            bit30 = (res >> 30) & 1;
+            /* of = result30 ^ result31 */
+            SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31);
+        }
+        break;
+        }
+    }
+    env->eip += decode->len;
+}
+
+void exec_rol(CPUX86State *env, struct x86_decode *decode)
+{
+    uint8_t count;
+
+    fetch_operands(env, decode, 2, true, true, false);
+    count = decode->op[1].val;
+
+    switch (decode->operand_size) {
+    case 1:
+    {
+        uint32_t bit0, bit7;
+        uint8_t res;
+
+        if ((count & 0x07) == 0) {
+            if (count & 0x18) {
+                bit0 = ((uint8_t)decode->op[0].val & 1);
+                bit7 = ((uint8_t)decode->op[0].val >> 7);
+                SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
+            }
+        }  else {
+            count &= 0x7; /* use only lowest 3 bits */
+            res = ((uint8_t)decode->op[0].val << count) |
+                   ((uint8_t)decode->op[0].val >> (8 - count));
+
+            write_val_ext(env, decode->op[0].ptr, res, 1);
+            /* set eflags:
+             * ROL count affects the following flags: C, O
+             */
+            bit0 = (res &  1);
+            bit7 = (res >> 7);
+            SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
+        }
+        break;
+    }
+    case 2:
+    {
+        uint32_t bit0, bit15;
+        uint16_t res;
+
+        if ((count & 0x0f) == 0) {
+            if (count & 0x10) {
+                bit0  = ((uint16_t)decode->op[0].val & 0x1);
+                bit15 = ((uint16_t)decode->op[0].val >> 15);
+                /* of = cf ^ result15 */
+                SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
+            }
+        } else {
+            count &= 0x0f; /* only use bottom 4 bits */
+            res = ((uint16_t)decode->op[0].val << count) |
+                   ((uint16_t)decode->op[0].val >> (16 - count));
+
+            write_val_ext(env, decode->op[0].ptr, res, 2);
+            bit0  = (res & 0x1);
+            bit15 = (res >> 15);
+            /* of = cf ^ result15 */
+            SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
+        }
+        break;
+    }
+    case 4:
+    {
+        uint32_t bit0, bit31;
+        uint32_t res;
+
+        count &= 0x1f;
+        if (count) {
+            res = ((uint32_t)decode->op[0].val << count) |
+                   ((uint32_t)decode->op[0].val >> (32 - count));
+
+            write_val_ext(env, decode->op[0].ptr, res, 4);
+            bit0  = (res & 0x1);
+            bit31 = (res >> 31);
+            /* of = cf ^ result31 */
+            SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0);
+        }
+        break;
+        }
+    }
+    env->eip += decode->len;
+}
+
+
+void exec_rcl(CPUX86State *env, struct x86_decode *decode)
+{
+    uint8_t count;
+    int of = 0, cf = 0;
+
+    fetch_operands(env, decode, 2, true, true, false);
+    count = decode->op[1].val & 0x1f;
+
+    switch (decode->operand_size) {
+    case 1:
+    {
+        uint8_t op1_8 = decode->op[0].val;
+        uint8_t res;
+        count %= 9;
+        if (!count) {
+            break;
+        }
+
+        if (1 == count) {
+            res = (op1_8 << 1) | get_CF(env);
+        } else {
+            res = (op1_8 << count) | (get_CF(env) << (count - 1)) |
+                   (op1_8 >> (9 - count));
+        }
+
+        write_val_ext(env, decode->op[0].ptr, res, 1);
+
+        cf = (op1_8 >> (8 - count)) & 0x01;
+        of = cf ^ (res >> 7); /* of = cf ^ result7 */
+        SET_FLAGS_OxxxxC(env, of, cf);
+        break;
+    }
+    case 2:
+    {
+        uint16_t res;
+        uint16_t op1_16 = decode->op[0].val;
+
+        count %= 17;
+        if (!count) {
+            break;
+        }
+
+        if (1 == count) {
+            res = (op1_16 << 1) | get_CF(env);
+        } else if (count == 16) {
+            res = (get_CF(env) << 15) | (op1_16 >> 1);
+        } else { /* 2..15 */
+            res = (op1_16 << count) | (get_CF(env) << (count - 1)) |
+                   (op1_16 >> (17 - count));
+        }
+
+        write_val_ext(env, decode->op[0].ptr, res, 2);
+
+        cf = (op1_16 >> (16 - count)) & 0x1;
+        of = cf ^ (res >> 15); /* of = cf ^ result15 */
+        SET_FLAGS_OxxxxC(env, of, cf);
+        break;
+    }
+    case 4:
+    {
+        uint32_t res;
+        uint32_t op1_32 = decode->op[0].val;
+
+        if (!count) {
+            break;
+        }
+
+        if (1 == count) {
+            res = (op1_32 << 1) | get_CF(env);
+        } else {
+            res = (op1_32 << count) | (get_CF(env) << (count - 1)) |
+                   (op1_32 >> (33 - count));
+        }
+
+        write_val_ext(env, decode->op[0].ptr, res, 4);
+
+        cf = (op1_32 >> (32 - count)) & 0x1;
+        of = cf ^ (res >> 31); /* of = cf ^ result31 */
+        SET_FLAGS_OxxxxC(env, of, cf);
+        break;
+        }
+    }
+    env->eip += decode->len;
+}
+
+void exec_rcr(CPUX86State *env, struct x86_decode *decode)
+{
+    uint8_t count;
+    int of = 0, cf = 0;
+
+    fetch_operands(env, decode, 2, true, true, false);
+    count = decode->op[1].val & 0x1f;
+
+    switch (decode->operand_size) {
+    case 1:
+    {
+        uint8_t op1_8 = decode->op[0].val;
+        uint8_t res;
+
+        count %= 9;
+        if (!count) {
+            break;
+        }
+        res = (op1_8 >> count) | (get_CF(env) << (8 - count)) |
+               (op1_8 << (9 - count));
+
+        write_val_ext(env, decode->op[0].ptr, res, 1);
+
+        cf = (op1_8 >> (count - 1)) & 0x1;
+        of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */
+        SET_FLAGS_OxxxxC(env, of, cf);
+        break;
+    }
+    case 2:
+    {
+        uint16_t op1_16 = decode->op[0].val;
+        uint16_t res;
+
+        count %= 17;
+        if (!count) {
+            break;
+        }
+        res = (op1_16 >> count) | (get_CF(env) << (16 - count)) |
+               (op1_16 << (17 - count));
+
+        write_val_ext(env, decode->op[0].ptr, res, 2);
+
+        cf = (op1_16 >> (count - 1)) & 0x1;
+        of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^
+                                                            result14 */
+        SET_FLAGS_OxxxxC(env, of, cf);
+        break;
+    }
+    case 4:
+    {
+        uint32_t res;
+        uint32_t op1_32 = decode->op[0].val;
+
+        if (!count) {
+            break;
+        }
+
+        if (1 == count) {
+            res = (op1_32 >> 1) | (get_CF(env) << 31);
+        } else {
+            res = (op1_32 >> count) | (get_CF(env) << (32 - count)) |
+                   (op1_32 << (33 - count));
+        }
+
+        write_val_ext(env, decode->op[0].ptr, res, 4);
+
+        cf = (op1_32 >> (count - 1)) & 0x1;
+        of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */
+        SET_FLAGS_OxxxxC(env, of, cf);
+        break;
+        }
+    }
+    env->eip += decode->len;
+}
+
+static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
+{
+    fetch_operands(env, decode, 2, true, true, false);
+
+    write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
+                  decode->operand_size);
+    write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
+                  decode->operand_size);
+
+    env->eip += decode->len;
+}
+
+static void exec_xadd(CPUX86State *env, struct x86_decode *decode)
+{
+    EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
+    write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
+                  decode->operand_size);
+
+    env->eip += decode->len;
+}
+
+static struct cmd_handler {
+    enum x86_decode_cmd cmd;
+    void (*handler)(CPUX86State *env, struct x86_decode *ins);
+} handlers[] = {
+    {X86_DECODE_CMD_INVL, NULL,},
+    {X86_DECODE_CMD_MOV, exec_mov},
+    {X86_DECODE_CMD_ADD, exec_add},
+    {X86_DECODE_CMD_OR, exec_or},
+    {X86_DECODE_CMD_ADC, exec_adc},
+    {X86_DECODE_CMD_SBB, exec_sbb},
+    {X86_DECODE_CMD_AND, exec_and},
+    {X86_DECODE_CMD_SUB, exec_sub},
+    {X86_DECODE_CMD_NEG, exec_neg},
+    {X86_DECODE_CMD_XOR, exec_xor},
+    {X86_DECODE_CMD_CMP, exec_cmp},
+    {X86_DECODE_CMD_INC, exec_inc},
+    {X86_DECODE_CMD_DEC, exec_dec},
+    {X86_DECODE_CMD_TST, exec_tst},
+    {X86_DECODE_CMD_NOT, exec_not},
+    {X86_DECODE_CMD_MOVZX, exec_movzx},
+    {X86_DECODE_CMD_OUT, exec_out},
+    {X86_DECODE_CMD_IN, exec_in},
+    {X86_DECODE_CMD_INS, exec_ins},
+    {X86_DECODE_CMD_OUTS, exec_outs},
+    {X86_DECODE_CMD_RDMSR, exec_rdmsr},
+    {X86_DECODE_CMD_WRMSR, exec_wrmsr},
+    {X86_DECODE_CMD_BT, exec_bt},
+    {X86_DECODE_CMD_BTR, exec_btr},
+    {X86_DECODE_CMD_BTC, exec_btc},
+    {X86_DECODE_CMD_BTS, exec_bts},
+    {X86_DECODE_CMD_SHL, exec_shl},
+    {X86_DECODE_CMD_ROL, exec_rol},
+    {X86_DECODE_CMD_ROR, exec_ror},
+    {X86_DECODE_CMD_RCR, exec_rcr},
+    {X86_DECODE_CMD_RCL, exec_rcl},
+    /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/
+    {X86_DECODE_CMD_MOVS, exec_movs},
+    {X86_DECODE_CMD_CMPS, exec_cmps},
+    {X86_DECODE_CMD_STOS, exec_stos},
+    {X86_DECODE_CMD_SCAS, exec_scas},
+    {X86_DECODE_CMD_LODS, exec_lods},
+    {X86_DECODE_CMD_MOVSX, exec_movsx},
+    {X86_DECODE_CMD_XCHG, exec_xchg},
+    {X86_DECODE_CMD_XADD, exec_xadd},
+};
+
+static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
+
+const struct x86_emul_ops *emul_ops;
+
+static void init_cmd_handler(void)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(handlers); i++) {
+        _cmd_handler[handlers[i].cmd] = handlers[i];
+    }
+}
+
+bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
+{
+    if (!_cmd_handler[ins->cmd].handler) {
+        printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip,
+                ins->cmd, ins->opcode[0],
+                ins->opcode_len > 1 ? ins->opcode[1] : 0);
+        env->eip += ins->len;
+        return true;
+    }
+
+    _cmd_handler[ins->cmd].handler(env, ins);
+    return true;
+}
+
+void init_emu(const struct x86_emul_ops *o)
+{
+    emul_ops = o;
+    init_cmd_handler();
+}
diff --git a/target/i386/emulate/x86_emu.h b/target/i386/emulate/x86_emu.h
new file mode 100644 (file)
index 0000000..555b567
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 Veertu Inc,
+ * Copyright (C) 2017 Google Inc,
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef X86_EMU_H
+#define X86_EMU_H
+
+#include "x86.h"
+#include "x86_decode.h"
+#include "cpu.h"
+
+struct x86_emul_ops {
+    void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
+    void (*write_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
+    void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc,
+                                    enum X86Seg seg);
+    void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction,
+                      int size, int count);
+    void (*simulate_rdmsr)(CPUState *cs);
+    void (*simulate_wrmsr)(CPUState *cs);
+};
+
+extern const struct x86_emul_ops *emul_ops;
+
+void init_emu(const struct x86_emul_ops *ops);
+bool exec_instruction(CPUX86State *env, struct x86_decode *ins);
+void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code);
+
+target_ulong read_reg(CPUX86State *env, int reg, int size);
+void write_reg(CPUX86State *env, int reg, target_ulong val, int size);
+target_ulong read_val_from_reg(target_ulong reg_ptr, int size);
+void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size);
+void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size);
+uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes);
+target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size);
+
+void exec_movzx(CPUX86State *env, struct x86_decode *decode);
+void exec_shl(CPUX86State *env, struct x86_decode *decode);
+void exec_movsx(CPUX86State *env, struct x86_decode *decode);
+void exec_ror(CPUX86State *env, struct x86_decode *decode);
+void exec_rol(CPUX86State *env, struct x86_decode *decode);
+void exec_rcl(CPUX86State *env, struct x86_decode *decode);
+void exec_rcr(CPUX86State *env, struct x86_decode *decode);
+#endif
diff --git a/target/i386/emulate/x86_flags.c b/target/i386/emulate/x86_flags.c
new file mode 100644 (file)
index 0000000..84e2736
--- /dev/null
@@ -0,0 +1,305 @@
+/////////////////////////////////////////////////////////////////////////
+//
+//  Copyright (C) 2001-2012  The Bochs Project
+//  Copyright (C) 2017 Google Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
+/////////////////////////////////////////////////////////////////////////
+/*
+ * flags functions
+ */
+
+#include "qemu/osdep.h"
+
+#include "panic.h"
+#include "cpu.h"
+#include "x86_flags.h"
+#include "x86.h"
+
+
+/* this is basically bocsh code */
+
+#define LF_SIGN_BIT     31
+
+#define LF_BIT_SD      (0)          /* lazy Sign Flag Delta            */
+#define LF_BIT_AF      (3)          /* lazy Adjust flag                */
+#define LF_BIT_PDB     (8)          /* lazy Parity Delta Byte (8 bits) */
+#define LF_BIT_CF      (31)         /* lazy Carry Flag                 */
+#define LF_BIT_PO      (30)         /* lazy Partial Overflow = CF ^ OF */
+
+#define LF_MASK_SD     (0x01 << LF_BIT_SD)
+#define LF_MASK_AF     (0x01 << LF_BIT_AF)
+#define LF_MASK_PDB    (0xFF << LF_BIT_PDB)
+#define LF_MASK_CF     (0x01 << LF_BIT_CF)
+#define LF_MASK_PO     (0x01 << LF_BIT_PO)
+
+/* ******************* */
+/* OSZAPC */
+/* ******************* */
+
+/* size, carries, result */
+#define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \
+    target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
+    (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
+    env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \
+    if ((size) == 32) { \
+        temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
+    } else if ((size) == 16) { \
+        temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
+    } else if ((size) == 8)  { \
+        temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
+    } else { \
+        VM_PANIC("unimplemented");  \
+    } \
+    env->lflags.auxbits = (target_ulong)(uint32_t)temp; \
+}
+
+/* carries, result */
+#define SET_FLAGS_OSZAPC_8(carries, result) \
+    SET_FLAGS_OSZAPC_SIZE(8, carries, result)
+#define SET_FLAGS_OSZAPC_16(carries, result) \
+    SET_FLAGS_OSZAPC_SIZE(16, carries, result)
+#define SET_FLAGS_OSZAPC_32(carries, result) \
+    SET_FLAGS_OSZAPC_SIZE(32, carries, result)
+
+/* ******************* */
+/* OSZAP */
+/* ******************* */
+/* size, carries, result */
+#define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \
+    target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
+    (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
+    if ((size) == 32) { \
+        temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
+    } else if ((size) == 16) { \
+        temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
+    } else if ((size) == 8) { \
+        temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
+    } else { \
+        VM_PANIC("unimplemented");      \
+    } \
+    env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \
+    target_ulong delta_c = (env->lflags.auxbits ^ temp) & LF_MASK_CF; \
+    delta_c ^= (delta_c >> 1); \
+    env->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \
+}
+
+/* carries, result */
+#define SET_FLAGS_OSZAP_8(carries, result) \
+    SET_FLAGS_OSZAP_SIZE(8, carries, result)
+#define SET_FLAGS_OSZAP_16(carries, result) \
+    SET_FLAGS_OSZAP_SIZE(16, carries, result)
+#define SET_FLAGS_OSZAP_32(carries, result) \
+    SET_FLAGS_OSZAP_SIZE(32, carries, result)
+
+void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf)
+{
+    uint32_t temp_po = new_of ^ new_cf;
+    env->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF);
+    env->lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF);
+}
+
+void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                            uint32_t diff)
+{
+    SET_FLAGS_OSZAPC_32(SUB_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                            uint16_t diff)
+{
+    SET_FLAGS_OSZAPC_16(SUB_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                            uint8_t diff)
+{
+    SET_FLAGS_OSZAPC_8(SUB_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                            uint32_t diff)
+{
+    SET_FLAGS_OSZAPC_32(ADD_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                            uint16_t diff)
+{
+    SET_FLAGS_OSZAPC_16(ADD_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                            uint8_t diff)
+{
+    SET_FLAGS_OSZAPC_8(ADD_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                            uint32_t diff)
+{
+    SET_FLAGS_OSZAP_32(SUB_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                            uint16_t diff)
+{
+    SET_FLAGS_OSZAP_16(SUB_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                            uint8_t diff)
+{
+    SET_FLAGS_OSZAP_8(SUB_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                            uint32_t diff)
+{
+    SET_FLAGS_OSZAP_32(ADD_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                            uint16_t diff)
+{
+    SET_FLAGS_OSZAP_16(ADD_COUT_VEC(v1, v2, diff), diff);
+}
+
+void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                            uint8_t diff)
+{
+    SET_FLAGS_OSZAP_8(ADD_COUT_VEC(v1, v2, diff), diff);
+}
+
+
+void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                              uint32_t diff)
+{
+    SET_FLAGS_OSZAPC_32(0, diff);
+}
+
+void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                              uint16_t diff)
+{
+    SET_FLAGS_OSZAPC_16(0, diff);
+}
+
+void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                             uint8_t diff)
+{
+    SET_FLAGS_OSZAPC_8(0, diff);
+}
+
+bool get_PF(CPUX86State *env)
+{
+    uint32_t temp = (255 & env->lflags.result);
+    temp = temp ^ (255 & (env->lflags.auxbits >> LF_BIT_PDB));
+    temp = (temp ^ (temp >> 4)) & 0x0F;
+    return (0x9669U >> temp) & 1;
+}
+
+void set_PF(CPUX86State *env, bool val)
+{
+    uint32_t temp = (255 & env->lflags.result) ^ (!val);
+    env->lflags.auxbits &= ~(LF_MASK_PDB);
+    env->lflags.auxbits |= (temp << LF_BIT_PDB);
+}
+
+bool get_OF(CPUX86State *env)
+{
+    return ((env->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1;
+}
+
+bool get_CF(CPUX86State *env)
+{
+    return (env->lflags.auxbits >> LF_BIT_CF) & 1;
+}
+
+void set_OF(CPUX86State *env, bool val)
+{
+    bool old_cf = get_CF(env);
+    SET_FLAGS_OxxxxC(env, val, old_cf);
+}
+
+void set_CF(CPUX86State *env, bool val)
+{
+    bool old_of = get_OF(env);
+    SET_FLAGS_OxxxxC(env, old_of, val);
+}
+
+bool get_AF(CPUX86State *env)
+{
+    return (env->lflags.auxbits >> LF_BIT_AF) & 1;
+}
+
+void set_AF(CPUX86State *env, bool val)
+{
+    env->lflags.auxbits &= ~(LF_MASK_AF);
+    env->lflags.auxbits |= val << LF_BIT_AF;
+}
+
+bool get_ZF(CPUX86State *env)
+{
+    return !env->lflags.result;
+}
+
+void set_ZF(CPUX86State *env, bool val)
+{
+    if (val) {
+        env->lflags.auxbits ^=
+         (((env->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD);
+        /* merge the parity bits into the Parity Delta Byte */
+        uint32_t temp_pdb = (255 & env->lflags.result);
+        env->lflags.auxbits ^= (temp_pdb << LF_BIT_PDB);
+        /* now zero the .result value */
+        env->lflags.result = 0;
+    } else {
+        env->lflags.result |= (1 << 8);
+    }
+}
+
+bool get_SF(CPUX86State *env)
+{
+    return ((env->lflags.result >> LF_SIGN_BIT) ^
+            (env->lflags.auxbits >> LF_BIT_SD)) & 1;
+}
+
+void set_SF(CPUX86State *env, bool val)
+{
+    bool temp_sf = get_SF(env);
+    env->lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD;
+}
+
+void lflags_to_rflags(CPUX86State *env)
+{
+    env->eflags &= ~(CC_C|CC_P|CC_A|CC_Z|CC_S|CC_O);
+    env->eflags |= get_CF(env) ? CC_C : 0;
+    env->eflags |= get_PF(env) ? CC_P : 0;
+    env->eflags |= get_AF(env) ? CC_A : 0;
+    env->eflags |= get_ZF(env) ? CC_Z : 0;
+    env->eflags |= get_SF(env) ? CC_S : 0;
+    env->eflags |= get_OF(env) ? CC_O : 0;
+}
+
+void rflags_to_lflags(CPUX86State *env)
+{
+    env->lflags.auxbits = env->lflags.result = 0;
+    set_OF(env, env->eflags & CC_O);
+    set_SF(env, env->eflags & CC_S);
+    set_ZF(env, env->eflags & CC_Z);
+    set_AF(env, env->eflags & CC_A);
+    set_PF(env, env->eflags & CC_P);
+    set_CF(env, env->eflags & CC_C);
+}
diff --git a/target/i386/emulate/x86_flags.h b/target/i386/emulate/x86_flags.h
new file mode 100644 (file)
index 0000000..6c17500
--- /dev/null
@@ -0,0 +1,81 @@
+/////////////////////////////////////////////////////////////////////////
+//
+//  Copyright (C) 2001-2012  The Bochs Project
+//  Copyright (C) 2017 Google Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
+/////////////////////////////////////////////////////////////////////////
+/*
+ * x86 eflags functions
+ */
+
+#ifndef X86_EMU_FLAGS_H
+#define X86_EMU_FLAGS_H
+
+#include "cpu.h"
+void lflags_to_rflags(CPUX86State *env);
+void rflags_to_lflags(CPUX86State *env);
+
+bool get_PF(CPUX86State *env);
+void set_PF(CPUX86State *env, bool val);
+bool get_CF(CPUX86State *env);
+void set_CF(CPUX86State *env, bool val);
+bool get_AF(CPUX86State *env);
+void set_AF(CPUX86State *env, bool val);
+bool get_ZF(CPUX86State *env);
+void set_ZF(CPUX86State *env, bool val);
+bool get_SF(CPUX86State *env);
+void set_SF(CPUX86State *env, bool val);
+bool get_OF(CPUX86State *env);
+void set_OF(CPUX86State *env, bool val);
+
+void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf);
+
+void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                            uint32_t diff);
+void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                            uint16_t diff);
+void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                           uint8_t diff);
+
+void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                            uint32_t diff);
+void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                            uint16_t diff);
+void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                           uint8_t diff);
+
+void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                           uint32_t diff);
+void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                           uint16_t diff);
+void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                          uint8_t diff);
+
+void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                           uint32_t diff);
+void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                           uint16_t diff);
+void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                          uint8_t diff);
+
+void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2,
+                              uint32_t diff);
+void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2,
+                              uint16_t diff);
+void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2,
+                             uint8_t diff);
+
+#endif /* X86_EMU_FLAGS_H */
index 8c31d2e0cf72c764ef7605976517e9778ff92f56..23ebf2550aca744396faccf53e1b140b6e617c64 100644 (file)
 #include "hvf-i386.h"
 #include "vmcs.h"
 #include "vmx.h"
-#include "x86.h"
+#include "emulate/x86.h"
 #include "x86_descr.h"
-#include "x86_flags.h"
+#include "emulate/x86_flags.h"
 #include "x86_mmu.h"
-#include "x86_decode.h"
-#include "x86_emu.h"
+#include "emulate/x86_decode.h"
+#include "emulate/x86_emu.h"
 #include "x86_task.h"
 #include "x86hvf.h"
 
index 05c3c8cf18b5fd377c91ac0d6b85077f856b90b6..519d190f0e6bb95e2860e17a730ae3ec6dc0b33a 100644 (file)
@@ -2,10 +2,7 @@ i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files(
   'hvf.c',
   'x86.c',
   'x86_cpuid.c',
-  'x86_decode.c',
   'x86_descr.c',
-  'x86_emu.c',
-  'x86_flags.c',
   'x86_mmu.c',
   'x86_task.c',
   'x86hvf.c',
index 80ce26279bf013a3aa1140edb54390c098fb762e..3c56afc9d3a16b38ec0933e094144f835b1227a3 100644 (file)
@@ -29,7 +29,7 @@
 #include <Hypervisor/hv_vmx.h>
 #include "vmcs.h"
 #include "cpu.h"
-#include "x86.h"
+#include "emulate/x86.h"
 #include "system/hvf.h"
 #include "system/hvf_int.h"
 
index a0ede138865eb31f52214e7fd6c49b0bac3f4f50..5c75ec9a007909c3716698821064a7c5f9c7712a 100644 (file)
@@ -19,8 +19,8 @@
 #include "qemu/osdep.h"
 
 #include "cpu.h"
-#include "x86_decode.h"
-#include "x86_emu.h"
+#include "emulate/x86_decode.h"
+#include "emulate/x86_emu.h"
 #include "vmcs.h"
 #include "vmx.h"
 #include "x86_mmu.h"
diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h
deleted file mode 100644 (file)
index 73edccf..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 2016 Veertu Inc,
- * Copyright (C) 2017 Veertu Inc,
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef X86_EMU_DEFS_H
-#define X86_EMU_DEFS_H
-
-typedef struct x86_register {
-    union {
-        struct {
-            uint64_t rrx;               /* full 64 bit */
-        };
-        struct {
-            uint32_t erx;               /* low 32 bit part */
-            uint32_t hi32_unused1;
-        };
-        struct {
-            uint16_t rx;                /* low 16 bit part */
-            uint16_t hi16_unused1;
-            uint32_t hi32_unused2;
-        };
-        struct {
-            uint8_t lx;                 /* low 8 bit part */
-            uint8_t hx;                 /* high 8 bit */
-            uint16_t hi16_unused2;
-            uint32_t hi32_unused3;
-        };
-    };
-} __attribute__ ((__packed__)) x86_register;
-
-/* 16 bit Task State Segment */
-typedef struct x86_tss_segment16 {
-    uint16_t link;
-    uint16_t sp0;
-    uint16_t ss0;
-    uint32_t sp1;
-    uint16_t ss1;
-    uint32_t sp2;
-    uint16_t ss2;
-    uint16_t ip;
-    uint16_t flags;
-    uint16_t ax;
-    uint16_t cx;
-    uint16_t dx;
-    uint16_t bx;
-    uint16_t sp;
-    uint16_t bp;
-    uint16_t si;
-    uint16_t di;
-    uint16_t es;
-    uint16_t cs;
-    uint16_t ss;
-    uint16_t ds;
-    uint16_t ldtr;
-} __attribute__((packed)) x86_tss_segment16;
-
-/* 32 bit Task State Segment */
-typedef struct x86_tss_segment32 {
-    uint32_t prev_tss;
-    uint32_t esp0;
-    uint32_t ss0;
-    uint32_t esp1;
-    uint32_t ss1;
-    uint32_t esp2;
-    uint32_t ss2;
-    uint32_t cr3;
-    uint32_t eip;
-    uint32_t eflags;
-    uint32_t eax;
-    uint32_t ecx;
-    uint32_t edx;
-    uint32_t ebx;
-    uint32_t esp;
-    uint32_t ebp;
-    uint32_t esi;
-    uint32_t edi;
-    uint32_t es;
-    uint32_t cs;
-    uint32_t ss;
-    uint32_t ds;
-    uint32_t fs;
-    uint32_t gs;
-    uint32_t ldt;
-    uint16_t trap;
-    uint16_t iomap_base;
-} __attribute__ ((__packed__)) x86_tss_segment32;
-
-/* 64 bit Task State Segment */
-typedef struct x86_tss_segment64 {
-    uint32_t unused;
-    uint64_t rsp0;
-    uint64_t rsp1;
-    uint64_t rsp2;
-    uint64_t unused1;
-    uint64_t ist1;
-    uint64_t ist2;
-    uint64_t ist3;
-    uint64_t ist4;
-    uint64_t ist5;
-    uint64_t ist6;
-    uint64_t ist7;
-    uint64_t unused2;
-    uint16_t unused3;
-    uint16_t iomap_base;
-} __attribute__ ((__packed__)) x86_tss_segment64;
-
-/* segment descriptors */
-typedef struct x86_segment_descriptor {
-    uint64_t    limit0:16;
-    uint64_t    base0:16;
-    uint64_t    base1:8;
-    uint64_t    type:4;
-    uint64_t    s:1;
-    uint64_t    dpl:2;
-    uint64_t    p:1;
-    uint64_t    limit1:4;
-    uint64_t    avl:1;
-    uint64_t    l:1;
-    uint64_t    db:1;
-    uint64_t    g:1;
-    uint64_t    base2:8;
-} __attribute__ ((__packed__)) x86_segment_descriptor;
-
-static inline uint32_t x86_segment_base(x86_segment_descriptor *desc)
-{
-    return (uint32_t)((desc->base2 << 24) | (desc->base1 << 16) | desc->base0);
-}
-
-static inline void x86_set_segment_base(x86_segment_descriptor *desc,
-                                        uint32_t base)
-{
-    desc->base2 = base >> 24;
-    desc->base1 = (base >> 16) & 0xff;
-    desc->base0 = base & 0xffff;
-}
-
-static inline uint32_t x86_segment_limit(x86_segment_descriptor *desc)
-{
-    uint32_t limit = (uint32_t)((desc->limit1 << 16) | desc->limit0);
-    if (desc->g) {
-        return (limit << 12) | 0xfff;
-    }
-    return limit;
-}
-
-static inline void x86_set_segment_limit(x86_segment_descriptor *desc,
-                                         uint32_t limit)
-{
-    desc->limit0 = limit & 0xffff;
-    desc->limit1 = limit >> 16;
-}
-
-typedef struct x86_call_gate {
-    uint64_t offset0:16;
-    uint64_t selector:16;
-    uint64_t param_count:4;
-    uint64_t reserved:3;
-    uint64_t type:4;
-    uint64_t dpl:1;
-    uint64_t p:1;
-    uint64_t offset1:16;
-} __attribute__ ((__packed__)) x86_call_gate;
-
-static inline uint32_t x86_call_gate_offset(x86_call_gate *gate)
-{
-    return (uint32_t)((gate->offset1 << 16) | gate->offset0);
-}
-
-#define GDT_SEL     0
-#define LDT_SEL     1
-
-typedef struct x86_segment_selector {
-    union {
-        uint16_t sel;
-        struct {
-            uint16_t rpl:2;
-            uint16_t ti:1;
-            uint16_t index:13;
-        };
-    };
-} __attribute__ ((__packed__)) x86_segment_selector;
-
-/* useful register access  macros */
-#define x86_reg(cpu, reg) ((x86_register *) &cpu->regs[reg])
-
-#define RRX(cpu, reg)   (x86_reg(cpu, reg)->rrx)
-#define RAX(cpu)        RRX(cpu, R_EAX)
-#define RCX(cpu)        RRX(cpu, R_ECX)
-#define RDX(cpu)        RRX(cpu, R_EDX)
-#define RBX(cpu)        RRX(cpu, R_EBX)
-#define RSP(cpu)        RRX(cpu, R_ESP)
-#define RBP(cpu)        RRX(cpu, R_EBP)
-#define RSI(cpu)        RRX(cpu, R_ESI)
-#define RDI(cpu)        RRX(cpu, R_EDI)
-#define R8(cpu)         RRX(cpu, R_R8)
-#define R9(cpu)         RRX(cpu, R_R9)
-#define R10(cpu)        RRX(cpu, R_R10)
-#define R11(cpu)        RRX(cpu, R_R11)
-#define R12(cpu)        RRX(cpu, R_R12)
-#define R13(cpu)        RRX(cpu, R_R13)
-#define R14(cpu)        RRX(cpu, R_R14)
-#define R15(cpu)        RRX(cpu, R_R15)
-
-#define ERX(cpu, reg)   (x86_reg(cpu, reg)->erx)
-#define EAX(cpu)        ERX(cpu, R_EAX)
-#define ECX(cpu)        ERX(cpu, R_ECX)
-#define EDX(cpu)        ERX(cpu, R_EDX)
-#define EBX(cpu)        ERX(cpu, R_EBX)
-#define ESP(cpu)        ERX(cpu, R_ESP)
-#define EBP(cpu)        ERX(cpu, R_EBP)
-#define ESI(cpu)        ERX(cpu, R_ESI)
-#define EDI(cpu)        ERX(cpu, R_EDI)
-
-#define RX(cpu, reg)   (x86_reg(cpu, reg)->rx)
-#define AX(cpu)        RX(cpu, R_EAX)
-#define CX(cpu)        RX(cpu, R_ECX)
-#define DX(cpu)        RX(cpu, R_EDX)
-#define BP(cpu)        RX(cpu, R_EBP)
-#define SP(cpu)        RX(cpu, R_ESP)
-#define BX(cpu)        RX(cpu, R_EBX)
-#define SI(cpu)        RX(cpu, R_ESI)
-#define DI(cpu)        RX(cpu, R_EDI)
-
-#define RL(cpu, reg)   (x86_reg(cpu, reg)->lx)
-#define AL(cpu)        RL(cpu, R_EAX)
-#define CL(cpu)        RL(cpu, R_ECX)
-#define DL(cpu)        RL(cpu, R_EDX)
-#define BL(cpu)        RL(cpu, R_EBX)
-
-#define RH(cpu, reg)   (x86_reg(cpu, reg)->hx)
-#define AH(cpu)        RH(cpu, R_EAX)
-#define CH(cpu)        RH(cpu, R_ECX)
-#define DH(cpu)        RH(cpu, R_EDX)
-#define BH(cpu)        RH(cpu, R_EBX)
-
-/* deal with GDT/LDT descriptors in memory */
-bool x86_read_segment_descriptor(CPUState *cpu,
-                                 struct x86_segment_descriptor *desc,
-                                 x86_segment_selector sel);
-bool x86_write_segment_descriptor(CPUState *cpu,
-                                  struct x86_segment_descriptor *desc,
-                                  x86_segment_selector sel);
-
-bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc,
-                        int gate);
-
-/* helpers */
-bool x86_is_protected(CPUState *cpu);
-bool x86_is_real(CPUState *cpu);
-bool x86_is_v8086(CPUState *cpu);
-bool x86_is_long_mode(CPUState *cpu);
-bool x86_is_long64_mode(CPUState *cpu);
-bool x86_is_paging_mode(CPUState *cpu);
-bool x86_is_pae_enabled(CPUState *cpu);
-
-enum X86Seg;
-target_ulong linear_addr(CPUState *cpu, target_ulong addr, enum X86Seg seg);
-target_ulong linear_addr_size(CPUState *cpu, target_ulong addr, int size,
-                              enum X86Seg seg);
-target_ulong linear_rip(CPUState *cpu, target_ulong rip);
-
-static inline uint64_t rdtscp(void)
-{
-    uint64_t tsc;
-    __asm__ __volatile__("rdtscp; "         /* serializing read of tsc */
-                         "shl $32,%%rdx; "  /* shift higher 32 bits stored in rdx up */
-                         "or %%rdx,%%rax"   /* and or onto rax */
-                         : "=a"(tsc)        /* output to tsc variable */
-                         :
-                         : "%rcx", "%rdx"); /* rcx and rdx are clobbered */
-
-    return tsc;
-}
-
-#endif
index ae836f65cc92d9abf650e8f36729df1745b759ba..fa131b18c6d17b2d830b197cceaa717370f84f93 100644 (file)
@@ -24,7 +24,7 @@
 #include "qemu/cpuid.h"
 #include "host/cpuinfo.h"
 #include "cpu.h"
-#include "x86.h"
+#include "emulate/x86.h"
 #include "vmx.h"
 #include "system/hvf.h"
 #include "hvf-i386.h"
diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c
deleted file mode 100644 (file)
index ddd7b60..0000000
+++ /dev/null
@@ -1,2194 +0,0 @@
-/*
- * Copyright (C) 2016 Veertu Inc,
- * Copyright (C) 2017 Google Inc,
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-
-#include "panic.h"
-#include "x86_decode.h"
-#include "x86_emu.h"
-
-#define OPCODE_ESCAPE   0xf
-
-static void decode_invalid(CPUX86State *env, struct x86_decode *decode)
-{
-    printf("%llx: failed to decode instruction ", env->eip);
-    for (int i = 0; i < decode->opcode_len; i++) {
-        printf("%x ", decode->opcode[i]);
-    }
-    printf("\n");
-    VM_PANIC("decoder failed\n");
-}
-
-uint64_t sign(uint64_t val, int size)
-{
-    switch (size) {
-    case 1:
-        val = (int8_t)val;
-        break;
-    case 2:
-        val = (int16_t)val;
-        break;
-    case 4:
-        val = (int32_t)val;
-        break;
-    case 8:
-        val = (int64_t)val;
-        break;
-    default:
-        VM_PANIC_EX("%s invalid size %d\n", __func__, size);
-        break;
-    }
-    return val;
-}
-
-static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode,
-                                    int size)
-{
-    uint64_t val = 0;
-
-    switch (size) {
-    case 1:
-    case 2:
-    case 4:
-    case 8:
-        break;
-    default:
-        VM_PANIC_EX("%s invalid size %d\n", __func__, size);
-        break;
-    }
-    target_ulong va  = linear_rip(env_cpu(env), env->eip) + decode->len;
-    emul_ops->read_mem(env_cpu(env), &val, va, size);
-    decode->len += size;
-    
-    return val;
-}
-
-static inline uint8_t decode_byte(CPUX86State *env, struct x86_decode *decode)
-{
-    return (uint8_t)decode_bytes(env, decode, 1);
-}
-
-static inline uint16_t decode_word(CPUX86State *env, struct x86_decode *decode)
-{
-    return (uint16_t)decode_bytes(env, decode, 2);
-}
-
-static inline uint32_t decode_dword(CPUX86State *env, struct x86_decode *decode)
-{
-    return (uint32_t)decode_bytes(env, decode, 4);
-}
-
-static inline uint64_t decode_qword(CPUX86State *env, struct x86_decode *decode)
-{
-    return decode_bytes(env, decode, 8);
-}
-
-static void decode_modrm_rm(CPUX86State *env, struct x86_decode *decode,
-                            struct x86_decode_op *op)
-{
-    op->type = X86_VAR_RM;
-}
-
-static void decode_modrm_reg(CPUX86State *env, struct x86_decode *decode,
-                             struct x86_decode_op *op)
-{
-    op->type = X86_VAR_REG;
-    op->reg = decode->modrm.reg;
-    op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.r,
-                          decode->operand_size);
-}
-
-static void decode_rax(CPUX86State *env, struct x86_decode *decode,
-                       struct x86_decode_op *op)
-{
-    op->type = X86_VAR_REG;
-    op->reg = R_EAX;
-    /* Since reg is always AX, REX prefix has no impact. */
-    op->ptr = get_reg_ref(env, op->reg, false, 0,
-                          decode->operand_size);
-}
-
-static inline void decode_immediate(CPUX86State *env, struct x86_decode *decode,
-                                    struct x86_decode_op *var, int size)
-{
-    var->type = X86_VAR_IMMEDIATE;
-    var->size = size;
-    switch (size) {
-    case 1:
-        var->val = decode_byte(env, decode);
-        break;
-    case 2:
-        var->val = decode_word(env, decode);
-        break;
-    case 4:
-        var->val = decode_dword(env, decode);
-        break;
-    case 8:
-        var->val = decode_qword(env, decode);
-        break;
-    default:
-        VM_PANIC_EX("bad size %d\n", size);
-    }
-}
-
-static void decode_imm8(CPUX86State *env, struct x86_decode *decode,
-                        struct x86_decode_op *op)
-{
-    decode_immediate(env, decode, op, 1);
-    op->type = X86_VAR_IMMEDIATE;
-}
-
-static void decode_imm8_signed(CPUX86State *env, struct x86_decode *decode,
-                               struct x86_decode_op *op)
-{
-    decode_immediate(env, decode, op, 1);
-    op->val = sign(op->val, 1);
-    op->type = X86_VAR_IMMEDIATE;
-}
-
-static void decode_imm16(CPUX86State *env, struct x86_decode *decode,
-                         struct x86_decode_op *op)
-{
-    decode_immediate(env, decode, op, 2);
-    op->type = X86_VAR_IMMEDIATE;
-}
-
-
-static void decode_imm(CPUX86State *env, struct x86_decode *decode,
-                       struct x86_decode_op *op)
-{
-    if (8 == decode->operand_size) {
-        decode_immediate(env, decode, op, 4);
-        op->val = sign(op->val, decode->operand_size);
-    } else {
-        decode_immediate(env, decode, op, decode->operand_size);
-    }
-    op->type = X86_VAR_IMMEDIATE;
-}
-
-static void decode_imm_signed(CPUX86State *env, struct x86_decode *decode,
-                              struct x86_decode_op *op)
-{
-    decode_immediate(env, decode, op, decode->operand_size);
-    op->val = sign(op->val, decode->operand_size);
-    op->type = X86_VAR_IMMEDIATE;
-}
-
-static void decode_imm_1(CPUX86State *env, struct x86_decode *decode,
-                         struct x86_decode_op *op)
-{
-    op->type = X86_VAR_IMMEDIATE;
-    op->val = 1;
-}
-
-static void decode_imm_0(CPUX86State *env, struct x86_decode *decode,
-                         struct x86_decode_op *op)
-{
-    op->type = X86_VAR_IMMEDIATE;
-    op->val = 0;
-}
-
-
-static void decode_pushseg(CPUX86State *env, struct x86_decode *decode)
-{
-    uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0];
-    
-    decode->op[0].type = X86_VAR_REG;
-    switch (op) {
-    case 0xe:
-        decode->op[0].reg = R_CS;
-        break;
-    case 0x16:
-        decode->op[0].reg = R_SS;
-        break;
-    case 0x1e:
-        decode->op[0].reg = R_DS;
-        break;
-    case 0x06:
-        decode->op[0].reg = R_ES;
-        break;
-    case 0xa0:
-        decode->op[0].reg = R_FS;
-        break;
-    case 0xa8:
-        decode->op[0].reg = R_GS;
-        break;
-    }
-}
-
-static void decode_popseg(CPUX86State *env, struct x86_decode *decode)
-{
-    uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0];
-    
-    decode->op[0].type = X86_VAR_REG;
-    switch (op) {
-    case 0xf:
-        decode->op[0].reg = R_CS;
-        break;
-    case 0x17:
-        decode->op[0].reg = R_SS;
-        break;
-    case 0x1f:
-        decode->op[0].reg = R_DS;
-        break;
-    case 0x07:
-        decode->op[0].reg = R_ES;
-        break;
-    case 0xa1:
-        decode->op[0].reg = R_FS;
-        break;
-    case 0xa9:
-        decode->op[0].reg = R_GS;
-        break;
-    }
-}
-
-static void decode_incgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_REG;
-    decode->op[0].reg = decode->opcode[0] - 0x40;
-    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
-                                    decode->rex.b, decode->operand_size);
-}
-
-static void decode_decgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_REG;
-    decode->op[0].reg = decode->opcode[0] - 0x48;
-    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
-                                    decode->rex.b, decode->operand_size);
-}
-
-static void decode_incgroup2(CPUX86State *env, struct x86_decode *decode)
-{
-    if (!decode->modrm.reg) {
-        decode->cmd = X86_DECODE_CMD_INC;
-    } else if (1 == decode->modrm.reg) {
-        decode->cmd = X86_DECODE_CMD_DEC;
-    }
-}
-
-static void decode_pushgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_REG;
-    decode->op[0].reg = decode->opcode[0] - 0x50;
-    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
-                                    decode->rex.b, decode->operand_size);
-}
-
-static void decode_popgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_REG;
-    decode->op[0].reg = decode->opcode[0] - 0x58;
-    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
-                                    decode->rex.b, decode->operand_size);
-}
-
-static void decode_jxx(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->displacement = decode_bytes(env, decode, decode->operand_size);
-    decode->displacement_size = decode->operand_size;
-}
-
-static void decode_farjmp(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_IMMEDIATE;
-    decode->op[0].val = decode_bytes(env, decode, decode->operand_size);
-    decode->displacement = decode_word(env, decode);
-}
-
-static void decode_addgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    enum x86_decode_cmd group[] = {
-        X86_DECODE_CMD_ADD,
-        X86_DECODE_CMD_OR,
-        X86_DECODE_CMD_ADC,
-        X86_DECODE_CMD_SBB,
-        X86_DECODE_CMD_AND,
-        X86_DECODE_CMD_SUB,
-        X86_DECODE_CMD_XOR,
-        X86_DECODE_CMD_CMP
-    };
-    decode->cmd = group[decode->modrm.reg];
-}
-
-static void decode_rotgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    enum x86_decode_cmd group[] = {
-        X86_DECODE_CMD_ROL,
-        X86_DECODE_CMD_ROR,
-        X86_DECODE_CMD_RCL,
-        X86_DECODE_CMD_RCR,
-        X86_DECODE_CMD_SHL,
-        X86_DECODE_CMD_SHR,
-        X86_DECODE_CMD_SHL,
-        X86_DECODE_CMD_SAR
-    };
-    decode->cmd = group[decode->modrm.reg];
-}
-
-static void decode_f7group(CPUX86State *env, struct x86_decode *decode)
-{
-    enum x86_decode_cmd group[] = {
-        X86_DECODE_CMD_TST,
-        X86_DECODE_CMD_TST,
-        X86_DECODE_CMD_NOT,
-        X86_DECODE_CMD_NEG,
-        X86_DECODE_CMD_MUL,
-        X86_DECODE_CMD_IMUL_1,
-        X86_DECODE_CMD_DIV,
-        X86_DECODE_CMD_IDIV
-    };
-    decode->cmd = group[decode->modrm.reg];
-    decode_modrm_rm(env, decode, &decode->op[0]);
-
-    switch (decode->modrm.reg) {
-    case 0:
-    case 1:
-        decode_imm(env, decode, &decode->op[1]);
-        break;
-    case 2:
-        break;
-    case 3:
-        decode->op[1].type = X86_VAR_IMMEDIATE;
-        decode->op[1].val = 0;
-        break;
-    default:
-        break;
-    }
-}
-
-static void decode_xchgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_REG;
-    decode->op[0].reg = decode->opcode[0] - 0x90;
-    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
-                                    decode->rex.b, decode->operand_size);
-}
-
-static void decode_movgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_REG;
-    decode->op[0].reg = decode->opcode[0] - 0xb8;
-    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
-                                    decode->rex.b, decode->operand_size);
-    decode_immediate(env, decode, &decode->op[1], decode->operand_size);
-}
-
-static void fetch_moffs(CPUX86State *env, struct x86_decode *decode,
-                        struct x86_decode_op *op)
-{
-    op->type = X86_VAR_OFFSET;
-    op->ptr = decode_bytes(env, decode, decode->addressing_size);
-}
-
-static void decode_movgroup8(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_REG;
-    decode->op[0].reg = decode->opcode[0] - 0xb0;
-    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
-                                    decode->rex.b, decode->operand_size);
-    decode_immediate(env, decode, &decode->op[1], decode->operand_size);
-}
-
-static void decode_rcx(CPUX86State *env, struct x86_decode *decode,
-                       struct x86_decode_op *op)
-{
-    op->type = X86_VAR_REG;
-    op->reg = R_ECX;
-    op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.b,
-                          decode->operand_size);
-}
-
-struct decode_tbl {
-    uint8_t opcode;
-    enum x86_decode_cmd cmd;
-    uint8_t operand_size;
-    bool is_modrm;
-    void (*decode_op1)(CPUX86State *env, struct x86_decode *decode,
-                       struct x86_decode_op *op1);
-    void (*decode_op2)(CPUX86State *env, struct x86_decode *decode,
-                       struct x86_decode_op *op2);
-    void (*decode_op3)(CPUX86State *env, struct x86_decode *decode,
-                       struct x86_decode_op *op3);
-    void (*decode_op4)(CPUX86State *env, struct x86_decode *decode,
-                       struct x86_decode_op *op4);
-    void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode);
-    uint32_t flags_mask;
-};
-
-struct decode_x87_tbl {
-    uint8_t opcode;
-    uint8_t modrm_reg;
-    uint8_t modrm_mod;
-    enum x86_decode_cmd cmd;
-    uint8_t operand_size;
-    bool rev;
-    bool pop;
-    void (*decode_op1)(CPUX86State *env, struct x86_decode *decode,
-                       struct x86_decode_op *op1);
-    void (*decode_op2)(CPUX86State *env, struct x86_decode *decode,
-                       struct x86_decode_op *op2);
-    void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode);
-    uint32_t flags_mask;
-};
-
-struct decode_tbl invl_inst = {0x0, 0, 0, false, NULL, NULL, NULL, NULL,
-                               decode_invalid};
-
-struct decode_tbl _decode_tbl1[256];
-struct decode_tbl _decode_tbl2[256];
-struct decode_x87_tbl _decode_tbl3[256];
-
-static void decode_x87_ins(CPUX86State *env, struct x86_decode *decode)
-{
-    struct decode_x87_tbl *decoder;
-    
-    decode->is_fpu = true;
-    int mode = decode->modrm.mod == 3 ? 1 : 0;
-    int index = ((decode->opcode[0] & 0xf) << 4) | (mode << 3) |
-                 decode->modrm.reg;
-
-    decoder = &_decode_tbl3[index];
-    
-    decode->cmd = decoder->cmd;
-    if (decoder->operand_size) {
-        decode->operand_size = decoder->operand_size;
-    }
-    decode->flags_mask = decoder->flags_mask;
-    decode->fpop_stack = decoder->pop;
-    decode->frev = decoder->rev;
-    
-    if (decoder->decode_op1) {
-        decoder->decode_op1(env, decode, &decode->op[0]);
-    }
-    if (decoder->decode_op2) {
-        decoder->decode_op2(env, decode, &decode->op[1]);
-    }
-    if (decoder->decode_postfix) {
-        decoder->decode_postfix(env, decode);
-    }
-
-    VM_PANIC_ON_EX(!decode->cmd, "x87 opcode %x %x (%x %x) not decoded\n",
-                   decode->opcode[0], decode->modrm.modrm, decoder->modrm_reg,
-                   decoder->modrm_mod);
-}
-
-static void decode_ffgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    enum x86_decode_cmd group[] = {
-        X86_DECODE_CMD_INC,
-        X86_DECODE_CMD_DEC,
-        X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT,
-        X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT,
-        X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT,
-        X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT,
-        X86_DECODE_CMD_PUSH,
-        X86_DECODE_CMD_INVL,
-        X86_DECODE_CMD_INVL
-    };
-    decode->cmd = group[decode->modrm.reg];
-    if (decode->modrm.reg > 2) {
-        decode->flags_mask = 0;
-    }
-}
-
-static void decode_sldtgroup(CPUX86State *env, struct x86_decode *decode)
-{
-
-    enum x86_decode_cmd group[] = {
-        X86_DECODE_CMD_SLDT,
-        X86_DECODE_CMD_STR,
-        X86_DECODE_CMD_LLDT,
-        X86_DECODE_CMD_LTR,
-        X86_DECODE_CMD_VERR,
-        X86_DECODE_CMD_VERW,
-        X86_DECODE_CMD_INVL,
-        X86_DECODE_CMD_INVL
-    };
-    decode->cmd = group[decode->modrm.reg];
-}
-
-static void decode_lidtgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    enum x86_decode_cmd group[] = {
-        X86_DECODE_CMD_SGDT,
-        X86_DECODE_CMD_SIDT,
-        X86_DECODE_CMD_LGDT,
-        X86_DECODE_CMD_LIDT,
-        X86_DECODE_CMD_SMSW,
-        X86_DECODE_CMD_LMSW,
-        X86_DECODE_CMD_LMSW,
-        X86_DECODE_CMD_INVLPG
-    };
-    decode->cmd = group[decode->modrm.reg];
-    if (0xf9 == decode->modrm.modrm) {
-        decode->opcode[decode->len++] = decode->modrm.modrm;
-        decode->cmd = X86_DECODE_CMD_RDTSCP;
-    }
-}
-
-static void decode_btgroup(CPUX86State *env, struct x86_decode *decode)
-{
-    enum x86_decode_cmd group[] = {
-        X86_DECODE_CMD_INVL,
-        X86_DECODE_CMD_INVL,
-        X86_DECODE_CMD_INVL,
-        X86_DECODE_CMD_INVL,
-        X86_DECODE_CMD_BT,
-        X86_DECODE_CMD_BTS,
-        X86_DECODE_CMD_BTR,
-        X86_DECODE_CMD_BTC
-    };
-    decode->cmd = group[decode->modrm.reg];
-}
-
-static void decode_x87_general(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->is_fpu = true;
-}
-
-static void decode_x87_modrm_floatp(CPUX86State *env, struct x86_decode *decode,
-                                    struct x86_decode_op *op)
-{
-    op->type = X87_VAR_FLOATP;
-}
-
-static void decode_x87_modrm_intp(CPUX86State *env, struct x86_decode *decode,
-                                  struct x86_decode_op *op)
-{
-    op->type = X87_VAR_INTP;
-}
-
-static void decode_x87_modrm_bytep(CPUX86State *env, struct x86_decode *decode,
-                                   struct x86_decode_op *op)
-{
-    op->type = X87_VAR_BYTEP;
-}
-
-static void decode_x87_modrm_st0(CPUX86State *env, struct x86_decode *decode,
-                                 struct x86_decode_op *op)
-{
-    op->type = X87_VAR_REG;
-    op->reg = 0;
-}
-
-static void decode_decode_x87_modrm_st0(CPUX86State *env,
-                                        struct x86_decode *decode,
-                                        struct x86_decode_op *op)
-{
-    op->type = X87_VAR_REG;
-    op->reg = decode->modrm.modrm & 7;
-}
-
-
-static void decode_aegroup(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->is_fpu = true;
-    switch (decode->modrm.reg) {
-    case 0:
-        decode->cmd = X86_DECODE_CMD_FXSAVE;
-        decode_x87_modrm_bytep(env, decode, &decode->op[0]);
-        break;
-    case 1:
-        decode_x87_modrm_bytep(env, decode, &decode->op[0]);
-        decode->cmd = X86_DECODE_CMD_FXRSTOR;
-        break;
-    case 5:
-        if (decode->modrm.modrm == 0xe8) {
-            decode->cmd = X86_DECODE_CMD_LFENCE;
-        } else {
-            VM_PANIC("xrstor");
-        }
-        break;
-    case 6:
-        VM_PANIC_ON(decode->modrm.modrm != 0xf0);
-        decode->cmd = X86_DECODE_CMD_MFENCE;
-        break;
-    case 7:
-        if (decode->modrm.modrm == 0xf8) {
-            decode->cmd = X86_DECODE_CMD_SFENCE;
-        } else {
-            decode->cmd = X86_DECODE_CMD_CLFLUSH;
-        }
-        break;
-    default:
-        VM_PANIC_EX("0xae: reg %d\n", decode->modrm.reg);
-        break;
-    }
-}
-
-static void decode_bswap(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_REG;
-    decode->op[0].reg = decode->opcode[1] - 0xc8;
-    decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
-                                    decode->rex.b, decode->operand_size);
-}
-
-static void decode_d9_4(CPUX86State *env, struct x86_decode *decode)
-{
-    switch (decode->modrm.modrm) {
-    case 0xe0:
-        /* FCHS */
-        decode->cmd = X86_DECODE_CMD_FCHS;
-        break;
-    case 0xe1:
-        decode->cmd = X86_DECODE_CMD_FABS;
-        break;
-    case 0xe4:
-        VM_PANIC("FTST");
-        break;
-    case 0xe5:
-        /* FXAM */
-        decode->cmd = X86_DECODE_CMD_FXAM;
-        break;
-    default:
-        VM_PANIC("FLDENV");
-        break;
-    }
-}
-
-static void decode_db_4(CPUX86State *env, struct x86_decode *decode)
-{
-    switch (decode->modrm.modrm) {
-    case 0xe0:
-        VM_PANIC_EX("unhandled FNENI: %x %x\n", decode->opcode[0],
-                    decode->modrm.modrm);
-        break;
-    case 0xe1:
-        VM_PANIC_EX("unhandled FNDISI: %x %x\n", decode->opcode[0],
-                    decode->modrm.modrm);
-        break;
-    case 0xe2:
-        VM_PANIC_EX("unhandled FCLEX: %x %x\n", decode->opcode[0],
-                    decode->modrm.modrm);
-        break;
-    case 0xe3:
-        decode->cmd = X86_DECODE_CMD_FNINIT;
-        break;
-    case 0xe4:
-        decode->cmd = X86_DECODE_CMD_FNSETPM;
-        break;
-    default:
-        VM_PANIC_EX("unhandled fpu opcode: %x %x\n", decode->opcode[0],
-                    decode->modrm.modrm);
-        break;
-    }
-}
-
-
-#define RFLAGS_MASK_NONE    0
-#define RFLAGS_MASK_OSZAPC  (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
-#define RFLAGS_MASK_LAHF    (CC_S | CC_Z | CC_A | CC_P | CC_C)
-#define RFLAGS_MASK_CF      (CC_C)
-#define RFLAGS_MASK_IF      (IF_MASK)
-#define RFLAGS_MASK_TF      (TF_MASK)
-#define RFLAGS_MASK_DF      (DF_MASK)
-#define RFLAGS_MASK_ZF      (CC_Z)
-
-struct decode_tbl _1op_inst[] = {
-    {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL,
-     NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x1, X86_DECODE_CMD_ADD, 0, true, decode_modrm_rm, decode_modrm_reg, NULL,
-     NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x2, X86_DECODE_CMD_ADD, 1, true, decode_modrm_reg, decode_modrm_rm, NULL,
-     NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x3, X86_DECODE_CMD_ADD, 0, true, decode_modrm_reg, decode_modrm_rm, NULL,
-     NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x4, X86_DECODE_CMD_ADD, 1, false, decode_rax, decode_imm8, NULL, NULL,
-     NULL, RFLAGS_MASK_OSZAPC},
-    {0x5, X86_DECODE_CMD_ADD, 0, false, decode_rax, decode_imm, NULL, NULL,
-     NULL, RFLAGS_MASK_OSZAPC},
-    {0x6, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL,
-     decode_pushseg, RFLAGS_MASK_NONE},
-    {0x7, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL,
-     decode_popseg, RFLAGS_MASK_NONE},
-    {0x8, X86_DECODE_CMD_OR, 1, true, decode_modrm_rm, decode_modrm_reg, NULL,
-     NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x9, X86_DECODE_CMD_OR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL,
-     NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xa, X86_DECODE_CMD_OR, 1, true, decode_modrm_reg, decode_modrm_rm, NULL,
-     NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xb, X86_DECODE_CMD_OR, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xc, X86_DECODE_CMD_OR, 1, false, decode_rax, decode_imm8,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xd, X86_DECODE_CMD_OR, 0, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0xe, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
-    {0xf, X86_DECODE_CMD_POP_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
-
-    {0x10, X86_DECODE_CMD_ADC, 1, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x11, X86_DECODE_CMD_ADC, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x12, X86_DECODE_CMD_ADC, 1, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x13, X86_DECODE_CMD_ADC, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x14, X86_DECODE_CMD_ADC, 1, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x15, X86_DECODE_CMD_ADC, 0, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0x16, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
-    {0x17, X86_DECODE_CMD_POP_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
-
-    {0x18, X86_DECODE_CMD_SBB, 1, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x19, X86_DECODE_CMD_SBB, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x1a, X86_DECODE_CMD_SBB, 1, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x1b, X86_DECODE_CMD_SBB, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x1c, X86_DECODE_CMD_SBB, 1, false, decode_rax, decode_imm8,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x1d, X86_DECODE_CMD_SBB, 0, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0x1e, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
-    {0x1f, X86_DECODE_CMD_POP_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
-
-    {0x20, X86_DECODE_CMD_AND, 1, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x21, X86_DECODE_CMD_AND, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x22, X86_DECODE_CMD_AND, 1, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x23, X86_DECODE_CMD_AND, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x24, X86_DECODE_CMD_AND, 1, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x25, X86_DECODE_CMD_AND, 0, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x28, X86_DECODE_CMD_SUB, 1, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x29, X86_DECODE_CMD_SUB, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x2a, X86_DECODE_CMD_SUB, 1, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x2b, X86_DECODE_CMD_SUB, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x2c, X86_DECODE_CMD_SUB, 1, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x2d, X86_DECODE_CMD_SUB, 0, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x2f, X86_DECODE_CMD_DAS, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x30, X86_DECODE_CMD_XOR, 1, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x31, X86_DECODE_CMD_XOR, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x32, X86_DECODE_CMD_XOR, 1, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x33, X86_DECODE_CMD_XOR, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x34, X86_DECODE_CMD_XOR, 1, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x35, X86_DECODE_CMD_XOR, 0, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0x38, X86_DECODE_CMD_CMP, 1, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x39, X86_DECODE_CMD_CMP, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x3a, X86_DECODE_CMD_CMP, 1, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x3b, X86_DECODE_CMD_CMP, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x3c, X86_DECODE_CMD_CMP, 1, false, decode_rax, decode_imm8,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x3d, X86_DECODE_CMD_CMP, 0, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0x3f, X86_DECODE_CMD_AAS, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0x40, X86_DECODE_CMD_INC, 0, false,
-     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
-    {0x41, X86_DECODE_CMD_INC, 0, false,
-     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
-    {0x42, X86_DECODE_CMD_INC, 0, false,
-     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
-    {0x43, X86_DECODE_CMD_INC, 0, false,
-     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
-    {0x44, X86_DECODE_CMD_INC, 0, false,
-     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
-    {0x45, X86_DECODE_CMD_INC, 0, false,
-     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
-    {0x46, X86_DECODE_CMD_INC, 0, false,
-     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
-    {0x47, X86_DECODE_CMD_INC, 0, false,
-     NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC},
-
-    {0x48, X86_DECODE_CMD_DEC, 0, false,
-     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
-    {0x49, X86_DECODE_CMD_DEC, 0, false,
-     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
-    {0x4a, X86_DECODE_CMD_DEC, 0, false,
-     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
-    {0x4b, X86_DECODE_CMD_DEC, 0, false,
-     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
-    {0x4c, X86_DECODE_CMD_DEC, 0, false,
-     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
-    {0x4d, X86_DECODE_CMD_DEC, 0, false,
-     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
-    {0x4e, X86_DECODE_CMD_DEC, 0, false,
-     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
-    {0x4f, X86_DECODE_CMD_DEC, 0, false,
-     NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC},
-
-    {0x50, X86_DECODE_CMD_PUSH, 0, false,
-     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
-    {0x51, X86_DECODE_CMD_PUSH, 0, false,
-     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
-    {0x52, X86_DECODE_CMD_PUSH, 0, false,
-     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
-    {0x53, X86_DECODE_CMD_PUSH, 0, false,
-     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
-    {0x54, X86_DECODE_CMD_PUSH, 0, false,
-     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
-    {0x55, X86_DECODE_CMD_PUSH, 0, false,
-     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
-    {0x56, X86_DECODE_CMD_PUSH, 0, false,
-     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
-    {0x57, X86_DECODE_CMD_PUSH, 0, false,
-     NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE},
-
-    {0x58, X86_DECODE_CMD_POP, 0, false,
-     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
-    {0x59, X86_DECODE_CMD_POP, 0, false,
-     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
-    {0x5a, X86_DECODE_CMD_POP, 0, false,
-     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
-    {0x5b, X86_DECODE_CMD_POP, 0, false,
-     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
-    {0x5c, X86_DECODE_CMD_POP, 0, false,
-     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
-    {0x5d, X86_DECODE_CMD_POP, 0, false,
-     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
-    {0x5e, X86_DECODE_CMD_POP, 0, false,
-     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
-    {0x5f, X86_DECODE_CMD_POP, 0, false,
-     NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE},
-
-    {0x60, X86_DECODE_CMD_PUSHA, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x61, X86_DECODE_CMD_POPA, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0x68, X86_DECODE_CMD_PUSH, 0, false, decode_imm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x6a, X86_DECODE_CMD_PUSH, 0, false, decode_imm8_signed,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x69, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg,
-     decode_modrm_rm, decode_imm, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x6b, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, decode_modrm_rm,
-     decode_imm8_signed, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0x6c, X86_DECODE_CMD_INS, 1, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x6d, X86_DECODE_CMD_INS, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x6e, X86_DECODE_CMD_OUTS, 1, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x6f, X86_DECODE_CMD_OUTS, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0x70, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x71, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x72, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x73, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x74, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x75, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x76, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x77, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x78, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x79, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x7a, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x7b, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x7c, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x7d, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x7e, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x7f, X86_DECODE_CMD_JXX, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-
-    {0x80, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8,
-     NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC},
-    {0x81, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm,
-     NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC},
-    {0x82, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8,
-     NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC},
-    {0x83, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8_signed,
-     NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC},
-    {0x84, X86_DECODE_CMD_TST, 1, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x85, X86_DECODE_CMD_TST, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0x86, X86_DECODE_CMD_XCHG, 1, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x87, X86_DECODE_CMD_XCHG, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x88, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x89, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x8a, X86_DECODE_CMD_MOV, 1, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x8b, X86_DECODE_CMD_MOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x8c, X86_DECODE_CMD_MOV_FROM_SEG, 0, true, decode_modrm_rm,
-     decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x8d, X86_DECODE_CMD_LEA, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x8e, X86_DECODE_CMD_MOV_TO_SEG, 0, true, decode_modrm_reg,
-     decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x8f, X86_DECODE_CMD_POP, 0, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0x90, X86_DECODE_CMD_NOP, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x91, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
-     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
-    {0x92, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
-     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
-    {0x93, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
-     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
-    {0x94, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
-     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
-    {0x95, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
-     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
-    {0x96, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
-     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
-    {0x97, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax,
-     NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE},
-
-    {0x98, X86_DECODE_CMD_CBW, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x99, X86_DECODE_CMD_CWD, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0x9a, X86_DECODE_CMD_CALL_FAR, 0, false, NULL,
-     NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE},
-
-    {0x9c, X86_DECODE_CMD_PUSHF, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    /*{0x9d, X86_DECODE_CMD_POPF, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_POPF},*/
-    {0x9e, X86_DECODE_CMD_SAHF, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x9f, X86_DECODE_CMD_LAHF, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_LAHF},
-
-    {0xa0, X86_DECODE_CMD_MOV, 1, false, decode_rax, fetch_moffs,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xa1, X86_DECODE_CMD_MOV, 0, false, decode_rax, fetch_moffs,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xa2, X86_DECODE_CMD_MOV, 1, false, fetch_moffs, decode_rax,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xa3, X86_DECODE_CMD_MOV, 0, false, fetch_moffs, decode_rax,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xa4, X86_DECODE_CMD_MOVS, 1, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xa5, X86_DECODE_CMD_MOVS, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xa6, X86_DECODE_CMD_CMPS, 1, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xa7, X86_DECODE_CMD_CMPS, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xaa, X86_DECODE_CMD_STOS, 1, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xab, X86_DECODE_CMD_STOS, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xac, X86_DECODE_CMD_LODS, 1, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xad, X86_DECODE_CMD_LODS, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xae, X86_DECODE_CMD_SCAS, 1, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xaf, X86_DECODE_CMD_SCAS, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0xa8, X86_DECODE_CMD_TST, 1, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xa9, X86_DECODE_CMD_TST, 0, false, decode_rax, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0xb0, X86_DECODE_CMD_MOV, 1, false, NULL,
-     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
-    {0xb1, X86_DECODE_CMD_MOV, 1, false, NULL,
-     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
-    {0xb2, X86_DECODE_CMD_MOV, 1, false, NULL,
-     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
-    {0xb3, X86_DECODE_CMD_MOV, 1, false, NULL,
-     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
-    {0xb4, X86_DECODE_CMD_MOV, 1, false, NULL,
-     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
-    {0xb5, X86_DECODE_CMD_MOV, 1, false, NULL,
-     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
-    {0xb6, X86_DECODE_CMD_MOV, 1, false, NULL,
-     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
-    {0xb7, X86_DECODE_CMD_MOV, 1, false, NULL,
-     NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE},
-
-    {0xb8, X86_DECODE_CMD_MOV, 0, false, NULL,
-     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
-    {0xb9, X86_DECODE_CMD_MOV, 0, false, NULL,
-     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
-    {0xba, X86_DECODE_CMD_MOV, 0, false, NULL,
-     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
-    {0xbb, X86_DECODE_CMD_MOV, 0, false, NULL,
-     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
-    {0xbc, X86_DECODE_CMD_MOV, 0, false, NULL,
-     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
-    {0xbd, X86_DECODE_CMD_MOV, 0, false, NULL,
-     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
-    {0xbe, X86_DECODE_CMD_MOV, 0, false, NULL,
-     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
-    {0xbf, X86_DECODE_CMD_MOV, 0, false, NULL,
-     NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE},
-
-    {0xc0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8,
-     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
-    {0xc1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8,
-     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
-
-    {0xc2, X86_DECODE_RET_NEAR, 0, false, decode_imm16,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xc3, X86_DECODE_RET_NEAR, 0, false, NULL,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xc4, X86_DECODE_CMD_LES, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xc5, X86_DECODE_CMD_LDS, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xc6, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_imm8,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xc7, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_imm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xc8, X86_DECODE_CMD_ENTER, 0, false, decode_imm16, decode_imm8,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xc9, X86_DECODE_CMD_LEAVE, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xca, X86_DECODE_RET_FAR, 0, false, decode_imm16, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xcb, X86_DECODE_RET_FAR, 0, false, decode_imm_0, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xcd, X86_DECODE_CMD_INT, 0, false, decode_imm8, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    /*{0xcf, X86_DECODE_CMD_IRET, 0, false, NULL, NULL,
-     NULL, NULL, NULL, RFLAGS_MASK_IRET},*/
-
-    {0xd0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm_1,
-     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
-    {0xd1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm_1,
-     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
-    {0xd2, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_rcx,
-     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
-    {0xd3, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_rcx,
-     NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC},
-
-    {0xd4, X86_DECODE_CMD_AAM, 0, false, decode_imm8,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xd5, X86_DECODE_CMD_AAD, 0, false, decode_imm8,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0xd7, X86_DECODE_CMD_XLAT, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xd8, X86_DECODE_CMD_INVL, 0, true, NULL,
-     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
-    {0xd9, X86_DECODE_CMD_INVL, 0, true, NULL,
-     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
-    {0xda, X86_DECODE_CMD_INVL, 0, true, NULL,
-     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
-    {0xdb, X86_DECODE_CMD_INVL, 0, true, NULL,
-     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
-    {0xdc, X86_DECODE_CMD_INVL, 0, true, NULL,
-     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
-    {0xdd, X86_DECODE_CMD_INVL, 0, true, NULL,
-     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
-    {0xde, X86_DECODE_CMD_INVL, 0, true, NULL,
-     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
-    {0xdf, X86_DECODE_CMD_INVL, 0, true, NULL,
-     NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE},
-
-    {0xe0, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xe1, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xe2, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xe3, X86_DECODE_CMD_JCXZ, 1, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-
-    {0xe4, X86_DECODE_CMD_IN, 1, false, decode_imm8,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xe5, X86_DECODE_CMD_IN, 0, false, decode_imm8,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xe6, X86_DECODE_CMD_OUT, 1, false, decode_imm8,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xe7, X86_DECODE_CMD_OUT, 0, false, decode_imm8,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xe8, X86_DECODE_CMD_CALL_NEAR, 0, false, decode_imm_signed,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xe9, X86_DECODE_CMD_JMP_NEAR, 0, false, decode_imm_signed,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xea, X86_DECODE_CMD_JMP_FAR, 0, false,
-     NULL, NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE},
-    {0xeb, X86_DECODE_CMD_JMP_NEAR, 1, false, decode_imm8_signed,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xec, X86_DECODE_CMD_IN, 1, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xed, X86_DECODE_CMD_IN, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xee, X86_DECODE_CMD_OUT, 1, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xef, X86_DECODE_CMD_OUT, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xf4, X86_DECODE_CMD_HLT, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xf5, X86_DECODE_CMD_CMC, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF},
-
-    {0xf6, X86_DECODE_CMD_INVL, 1, true,
-     NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC},
-    {0xf7, X86_DECODE_CMD_INVL, 0, true,
-     NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC},
-
-    {0xf8, X86_DECODE_CMD_CLC, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF},
-    {0xf9, X86_DECODE_CMD_STC, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF},
-
-    {0xfa, X86_DECODE_CMD_CLI, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF},
-    {0xfb, X86_DECODE_CMD_STI, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF},
-    {0xfc, X86_DECODE_CMD_CLD, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF},
-    {0xfd, X86_DECODE_CMD_STD, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF},
-    {0xfe, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, decode_incgroup2, RFLAGS_MASK_OSZAPC},
-    {0xff, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm,
-     NULL, NULL, NULL, decode_ffgroup, RFLAGS_MASK_OSZAPC},
-};
-
-struct decode_tbl _2op_inst[] = {
-    {0x0, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm,
-     NULL, NULL, NULL, decode_sldtgroup, RFLAGS_MASK_NONE},
-    {0x1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm,
-     NULL, NULL, NULL, decode_lidtgroup, RFLAGS_MASK_NONE},
-    {0x6, X86_DECODE_CMD_CLTS, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_TF},
-    {0x9, X86_DECODE_CMD_WBINVD, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x18, X86_DECODE_CMD_PREFETCH, 0, true,
-     NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE},
-    {0x1f, X86_DECODE_CMD_NOP, 0, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x20, X86_DECODE_CMD_MOV_FROM_CR, 0, true, decode_modrm_rm,
-     decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x21, X86_DECODE_CMD_MOV_FROM_DR, 0, true, decode_modrm_rm,
-     decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x22, X86_DECODE_CMD_MOV_TO_CR, 0, true, decode_modrm_reg,
-     decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x23, X86_DECODE_CMD_MOV_TO_DR, 0, true, decode_modrm_reg,
-     decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x30, X86_DECODE_CMD_WRMSR, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x31, X86_DECODE_CMD_RDTSC, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x32, X86_DECODE_CMD_RDMSR, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x40, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x41, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x42, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x43, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x44, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x45, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x46, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x47, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x48, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x49, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x4a, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x4b, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x4c, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x4d, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x4e, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x4f, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x77, X86_DECODE_CMD_EMMS, 0, false,
-     NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE},
-    {0x82, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x83, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x84, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x85, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x86, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x87, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x88, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x89, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x8a, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x8b, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x8c, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x8d, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x8e, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x8f, X86_DECODE_CMD_JXX, 0, false,
-     NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE},
-    {0x90, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x91, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x92, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x93, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x94, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x95, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x96, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x97, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x98, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x99, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x9a, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x9b, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x9c, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x9d, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x9e, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0x9f, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xb0, X86_DECODE_CMD_CMPXCHG, 1, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xb1, X86_DECODE_CMD_CMPXCHG, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xb6, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xb7, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xb8, X86_DECODE_CMD_POPCNT, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xbe, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xbf, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xa0, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
-    {0xa1, X86_DECODE_CMD_POP_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
-    {0xa2, X86_DECODE_CMD_CPUID, 0, false,
-     NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xa3, X86_DECODE_CMD_BT, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_CF},
-    {0xa4, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg,
-     decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xa5, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg,
-     decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xa8, X86_DECODE_CMD_PUSH_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE},
-    {0xa9, X86_DECODE_CMD_POP_SEG, 0, false, false,
-     NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE},
-    {0xab, X86_DECODE_CMD_BTS, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_CF},
-    {0xac, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg,
-     decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xad, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg,
-     decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0xae, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm,
-     NULL, NULL, NULL, decode_aegroup, RFLAGS_MASK_NONE},
-
-    {0xaf, X86_DECODE_CMD_IMUL_2, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xb2, X86_DECODE_CMD_LSS, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xb3, X86_DECODE_CMD_BTR, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xba, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8,
-     NULL, NULL, decode_btgroup, RFLAGS_MASK_OSZAPC},
-    {0xbb, X86_DECODE_CMD_BTC, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xbc, X86_DECODE_CMD_BSF, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-    {0xbd, X86_DECODE_CMD_BSR, 0, true, decode_modrm_reg, decode_modrm_rm,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0xc1, X86_DECODE_CMD_XADD, 0, true, decode_modrm_rm, decode_modrm_reg,
-     NULL, NULL, NULL, RFLAGS_MASK_OSZAPC},
-
-    {0xc7, X86_DECODE_CMD_CMPXCHG8B, 0, true, decode_modrm_rm,
-     NULL, NULL, NULL, NULL, RFLAGS_MASK_ZF},
-
-    {0xc8, X86_DECODE_CMD_BSWAP, 0, false,
-     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
-    {0xc9, X86_DECODE_CMD_BSWAP, 0, false,
-     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
-    {0xca, X86_DECODE_CMD_BSWAP, 0, false,
-     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
-    {0xcb, X86_DECODE_CMD_BSWAP, 0, false,
-     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
-    {0xcc, X86_DECODE_CMD_BSWAP, 0, false,
-     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
-    {0xcd, X86_DECODE_CMD_BSWAP, 0, false,
-     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
-    {0xce, X86_DECODE_CMD_BSWAP, 0, false,
-     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
-    {0xcf, X86_DECODE_CMD_BSWAP, 0, false,
-     NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE},
-};
-
-struct decode_x87_tbl invl_inst_x87 = {0x0, 0, 0, 0, 0, false, false, NULL,
-                                       NULL, decode_invalid, 0};
-
-struct decode_x87_tbl _x87_inst[] = {
-    {0xd8, 0, 3, X86_DECODE_CMD_FADD, 10, false, false,
-     decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, decode_x87_modrm_st0,
-     decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 4, 3, X86_DECODE_CMD_FSUB, 10, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 5, 3, X86_DECODE_CMD_FSUB, 10, true, false, decode_x87_modrm_st0,
-     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0,
-     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 6, 3, X86_DECODE_CMD_FDIV, 10, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 7, 3, X86_DECODE_CMD_FDIV, 10, true, false, decode_x87_modrm_st0,
-     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xd8, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0,
-     decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-
-    {0xd9, 0, 3, X86_DECODE_CMD_FLD, 10, false, false,
-     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 0, 0, X86_DECODE_CMD_FLD, 4, false, false,
-     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 1, 0, X86_DECODE_CMD_INVL, 10, false, false,
-     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 2, 3, X86_DECODE_CMD_INVL, 10, false, false,
-     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 2, 0, X86_DECODE_CMD_FST, 4, false, false,
-     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 3, 3, X86_DECODE_CMD_INVL, 10, false, false,
-     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 3, 0, X86_DECODE_CMD_FST, 4, false, true,
-     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 4, 3, X86_DECODE_CMD_INVL, 10, false, false,
-     decode_x87_modrm_st0, NULL, decode_d9_4, RFLAGS_MASK_NONE},
-    {0xd9, 4, 0, X86_DECODE_CMD_INVL, 4, false, false,
-     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 5, 3, X86_DECODE_CMD_FLDxx, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
-    {0xd9, 5, 0, X86_DECODE_CMD_FLDCW, 2, false, false,
-     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xd9, 7, 3, X86_DECODE_CMD_FNSTCW, 2, false, false,
-     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xd9, 7, 0, X86_DECODE_CMD_FNSTCW, 2, false, false,
-     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xda, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xda, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xda, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0,
-     decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xda, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xda, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xda, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xda, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
-    {0xda, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xda, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, decode_x87_modrm_st0,
-     decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xda, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0,
-     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xda, 6, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
-    {0xda, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xda, 7, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
-    {0xda, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0,
-     decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-
-    {0xdb, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0,
-     decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdb, 0, 0, X86_DECODE_CMD_FLD, 4, false, false,
-     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdb, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdb, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdb, 2, 0, X86_DECODE_CMD_FST, 4, false, false,
-     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdb, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdb, 3, 0, X86_DECODE_CMD_FST, 4, false, true,
-     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdb, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL,
-     decode_db_4, RFLAGS_MASK_NONE},
-    {0xdb, 4, 0, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
-    {0xdb, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdb, 5, 0, X86_DECODE_CMD_FLD, 10, false, false,
-     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdb, 7, 0, X86_DECODE_CMD_FST, 10, false, true,
-     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xdc, 0, 3, X86_DECODE_CMD_FADD, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 0, 0, X86_DECODE_CMD_FADD, 8, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 1, 0, X86_DECODE_CMD_FMUL, 8, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 4, 3, X86_DECODE_CMD_FSUB, 10, true, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 4, 0, X86_DECODE_CMD_FSUB, 8, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 5, 3, X86_DECODE_CMD_FSUB, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 5, 0, X86_DECODE_CMD_FSUB, 8, true, false,
-     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 6, 3, X86_DECODE_CMD_FDIV, 10, true, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 6, 0, X86_DECODE_CMD_FDIV, 8, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 7, 3, X86_DECODE_CMD_FDIV, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdc, 7, 0, X86_DECODE_CMD_FDIV, 8, true, false,
-     decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE},
-
-    {0xdd, 0, 0, X86_DECODE_CMD_FLD, 8, false, false,
-     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 2, 3, X86_DECODE_CMD_FST, 10, false, false,
-     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 2, 0, X86_DECODE_CMD_FST, 8, false, false,
-     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 3, 3, X86_DECODE_CMD_FST, 10, false, true,
-     decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 3, 0, X86_DECODE_CMD_FST, 8, false, true,
-     decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 4, 3, X86_DECODE_CMD_FUCOM, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 4, 0, X86_DECODE_CMD_FRSTOR, 8, false, false,
-     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 7, 0, X86_DECODE_CMD_FNSTSW, 0, false, false,
-     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdd, 7, 3, X86_DECODE_CMD_FNSTSW, 0, false, false,
-     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
-
-    {0xde, 0, 3, X86_DECODE_CMD_FADD, 10, false, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xde, 0, 0, X86_DECODE_CMD_FADD, 2, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xde, 1, 3, X86_DECODE_CMD_FMUL, 10, false, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xde, 1, 0, X86_DECODE_CMD_FMUL, 2, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xde, 4, 3, X86_DECODE_CMD_FSUB, 10, true, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xde, 4, 0, X86_DECODE_CMD_FSUB, 2, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xde, 5, 3, X86_DECODE_CMD_FSUB, 10, false, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xde, 5, 0, X86_DECODE_CMD_FSUB, 2, true, false,
-     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xde, 6, 3, X86_DECODE_CMD_FDIV, 10, true, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xde, 6, 0, X86_DECODE_CMD_FDIV, 2, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-    {0xde, 7, 3, X86_DECODE_CMD_FDIV, 10, false, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xde, 7, 0, X86_DECODE_CMD_FDIV, 2, true, false,
-     decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE},
-
-    {0xdf, 0, 0, X86_DECODE_CMD_FLD, 2, false, false,
-     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdf, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdf, 2, 3, X86_DECODE_CMD_FST, 10, false, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdf, 2, 0, X86_DECODE_CMD_FST, 2, false, false,
-     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdf, 3, 3, X86_DECODE_CMD_FST, 10, false, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdf, 3, 0, X86_DECODE_CMD_FST, 2, false, true,
-     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdf, 4, 3, X86_DECODE_CMD_FNSTSW, 2, false, true,
-     decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdf, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, true,
-     decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE},
-    {0xdf, 5, 0, X86_DECODE_CMD_FLD, 8, false, false,
-     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
-    {0xdf, 7, 0, X86_DECODE_CMD_FST, 8, false, true,
-     decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE},
-};
-
-void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode,
-                          struct x86_decode_op *op)
-{
-    target_ulong ptr = 0;
-    X86Seg seg = R_DS;
-
-    if (!decode->modrm.mod && 6 == decode->modrm.rm) {
-        ptr = decode->displacement;
-        goto calc_addr;
-    }
-
-    if (decode->displacement_size) {
-        ptr = sign(decode->displacement, decode->displacement_size);
-    }
-
-    switch (decode->modrm.rm) {
-    case 0:
-        ptr += BX(env) + SI(env);
-        break;
-    case 1:
-        ptr += BX(env) + DI(env);
-        break;
-    case 2:
-        ptr += BP(env) + SI(env);
-        seg = R_SS;
-        break;
-    case 3:
-        ptr += BP(env) + DI(env);
-        seg = R_SS;
-        break;
-    case 4:
-        ptr += SI(env);
-        break;
-    case 5:
-        ptr += DI(env);
-        break;
-    case 6:
-        ptr += BP(env);
-        seg = R_SS;
-        break;
-    case 7:
-        ptr += BX(env);
-        break;
-    }
-calc_addr:
-    if (X86_DECODE_CMD_LEA == decode->cmd) {
-        op->ptr = (uint16_t)ptr;
-    } else {
-        op->ptr = decode_linear_addr(env, decode, (uint16_t)ptr, seg);
-    }
-}
-
-target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present,
-                         int is_extended, int size)
-{
-    target_ulong ptr = 0;
-
-    if (is_extended) {
-        reg |= R_R8;
-    }
-
-    switch (size) {
-    case 1:
-        if (is_extended || reg < 4 || rex_present) {
-            ptr = (target_ulong)&RL(env, reg);
-        } else {
-            ptr = (target_ulong)&RH(env, reg - 4);
-        }
-        break;
-    default:
-        ptr = (target_ulong)&RRX(env, reg);
-        break;
-    }
-    return ptr;
-}
-
-target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present,
-                         int is_extended, int size)
-{
-    target_ulong val = 0;
-    memcpy(&val,
-           (void *)get_reg_ref(env, reg, rex_present, is_extended, size),
-           size);
-    return val;
-}
-
-static target_ulong get_sib_val(CPUX86State *env, struct x86_decode *decode,
-                          X86Seg *sel)
-{
-    target_ulong base = 0;
-    target_ulong scaled_index = 0;
-    int addr_size = decode->addressing_size;
-    int base_reg = decode->sib.base;
-    int index_reg = decode->sib.index;
-
-    *sel = R_DS;
-
-    if (decode->modrm.mod || base_reg != R_EBP) {
-        if (decode->rex.b) {
-            base_reg |= R_R8;
-        }
-        if (base_reg == R_ESP || base_reg == R_EBP) {
-            *sel = R_SS;
-        }
-        base = get_reg_val(env, decode->sib.base, decode->rex.rex,
-                           decode->rex.b, addr_size);
-    }
-
-    if (decode->rex.x) {
-        index_reg |= R_R8;
-    }
-
-    if (index_reg != R_ESP) {
-        scaled_index = get_reg_val(env, index_reg, decode->rex.rex,
-                                   decode->rex.x, addr_size) <<
-                                   decode->sib.scale;
-    }
-    return base + scaled_index;
-}
-
-void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode,
-                          struct x86_decode_op *op)
-{
-    X86Seg seg = R_DS;
-    target_ulong ptr = 0;
-    int addr_size = decode->addressing_size;
-
-    if (decode->displacement_size) {
-        ptr = sign(decode->displacement, decode->displacement_size);
-    }
-
-    if (4 == decode->modrm.rm) {
-        ptr += get_sib_val(env, decode, &seg);
-    } else if (!decode->modrm.mod && 5 == decode->modrm.rm) {
-        if (x86_is_long_mode(env_cpu(env))) {
-            ptr += env->eip + decode->len;
-        } else {
-            ptr = decode->displacement;
-        }
-    } else {
-        if (decode->modrm.rm == R_EBP || decode->modrm.rm == R_ESP) {
-            seg = R_SS;
-        }
-        ptr += get_reg_val(env, decode->modrm.rm, decode->rex.rex,
-                           decode->rex.b, addr_size);
-    }
-
-    if (X86_DECODE_CMD_LEA == decode->cmd) {
-        op->ptr = (uint32_t)ptr;
-    } else {
-        op->ptr = decode_linear_addr(env, decode, (uint32_t)ptr, seg);
-    }
-}
-
-void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode,
-                          struct x86_decode_op *op)
-{
-    X86Seg seg = R_DS;
-    int32_t offset = 0;
-    int mod = decode->modrm.mod;
-    int rm = decode->modrm.rm;
-    target_ulong ptr;
-    int src = decode->modrm.rm;
-
-    if (decode->displacement_size) {
-        offset = sign(decode->displacement, decode->displacement_size);
-    }
-
-    if (4 == rm) {
-        ptr = get_sib_val(env, decode, &seg) + offset;
-    } else if (0 == mod && 5 == rm) {
-        ptr = env->eip + decode->len + (int32_t) offset;
-    } else {
-        ptr = get_reg_val(env, src, decode->rex.rex, decode->rex.b, 8) +
-              (int64_t) offset;
-    }
-
-    if (X86_DECODE_CMD_LEA == decode->cmd) {
-        op->ptr = ptr;
-    } else {
-        op->ptr = decode_linear_addr(env, decode, ptr, seg);
-    }
-}
-
-
-void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,
-                        struct x86_decode_op *op)
-{
-    if (3 == decode->modrm.mod) {
-        op->reg = decode->modrm.reg;
-        op->type = X86_VAR_REG;
-        op->ptr = get_reg_ref(env, decode->modrm.rm, decode->rex.rex,
-                              decode->rex.b, decode->operand_size);
-        return;
-    }
-
-    switch (decode->addressing_size) {
-    case 2:
-        calc_modrm_operand16(env, decode, op);
-        break;
-    case 4:
-        calc_modrm_operand32(env, decode, op);
-        break;
-    case 8:
-        calc_modrm_operand64(env, decode, op);
-        break;
-    default:
-        VM_PANIC_EX("unsupported address size %d\n", decode->addressing_size);
-        break;
-    }
-}
-
-static void decode_prefix(CPUX86State *env, struct x86_decode *decode)
-{
-    while (1) {
-        /*
-         * REX prefix must come after legacy prefixes.
-         * REX before legacy is ignored.
-         * Clear rex to simulate this.
-         */
-        uint8_t byte = decode_byte(env, decode);
-        switch (byte) {
-        case PREFIX_LOCK:
-            decode->lock = byte;
-            decode->rex.rex = 0;
-            break;
-        case PREFIX_REPN:
-        case PREFIX_REP:
-            decode->rep = byte;
-            decode->rex.rex = 0;
-            break;
-        case PREFIX_CS_SEG_OVERRIDE:
-        case PREFIX_SS_SEG_OVERRIDE:
-        case PREFIX_DS_SEG_OVERRIDE:
-        case PREFIX_ES_SEG_OVERRIDE:
-        case PREFIX_FS_SEG_OVERRIDE:
-        case PREFIX_GS_SEG_OVERRIDE:
-            decode->segment_override = byte;
-            decode->rex.rex = 0;
-            break;
-        case PREFIX_OP_SIZE_OVERRIDE:
-            decode->op_size_override = byte;
-            decode->rex.rex = 0;
-            break;
-        case PREFIX_ADDR_SIZE_OVERRIDE:
-            decode->addr_size_override = byte;
-            decode->rex.rex = 0;
-            break;
-        case PREFIX_REX ... (PREFIX_REX + 0xf):
-            if (x86_is_long_mode(env_cpu(env))) {
-                decode->rex.rex = byte;
-                break;
-            }
-            /* fall through when not in long mode */
-        default:
-            decode->len--;
-            return;
-        }
-    }
-}
-
-void set_addressing_size(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->addressing_size = -1;
-    if (x86_is_real(env_cpu(env)) || x86_is_v8086(env_cpu(env))) {
-        if (decode->addr_size_override) {
-            decode->addressing_size = 4;
-        } else {
-            decode->addressing_size = 2;
-        }
-    } else if (!x86_is_long_mode(env_cpu(env))) {
-        /* protected */
-        x86_segment_descriptor cs;
-        emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS);
-        /* check db */
-        if (cs.db) {
-            if (decode->addr_size_override) {
-                decode->addressing_size = 2;
-            } else {
-                decode->addressing_size = 4;
-            }
-        } else {
-            if (decode->addr_size_override) {
-                decode->addressing_size = 4;
-            } else {
-                decode->addressing_size = 2;
-            }
-        }
-    } else {
-        /* long */
-        if (decode->addr_size_override) {
-            decode->addressing_size = 4;
-        } else {
-            decode->addressing_size = 8;
-        }
-    }
-}
-
-void set_operand_size(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->operand_size = -1;
-    if (x86_is_real(env_cpu(env)) || x86_is_v8086(env_cpu(env))) {
-        if (decode->op_size_override) {
-            decode->operand_size = 4;
-        } else {
-            decode->operand_size = 2;
-        }
-    } else if (!x86_is_long_mode(env_cpu(env))) {
-        /* protected */
-        x86_segment_descriptor cs;
-        emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS);
-        /* check db */
-        if (cs.db) {
-            if (decode->op_size_override) {
-                decode->operand_size = 2;
-            } else{
-                decode->operand_size = 4;
-            }
-        } else {
-            if (decode->op_size_override) {
-                decode->operand_size = 4;
-            } else {
-                decode->operand_size = 2;
-            }
-        }
-    } else {
-        /* long */
-        if (decode->op_size_override) {
-            decode->operand_size = 2;
-        } else {
-            decode->operand_size = 4;
-        }
-
-        if (decode->rex.w) {
-            decode->operand_size = 8;
-        }
-    }
-}
-
-static void decode_sib(CPUX86State *env, struct x86_decode *decode)
-{
-    if ((decode->modrm.mod != 3) && (4 == decode->modrm.rm) &&
-        (decode->addressing_size != 2)) {
-        decode->sib.sib = decode_byte(env, decode);
-        decode->sib_present = true;
-    }
-}
-
-/* 16 bit modrm */
-int disp16_tbl[4][8] = {
-    {0, 0, 0, 0, 0, 0, 2, 0},
-    {1, 1, 1, 1, 1, 1, 1, 1},
-    {2, 2, 2, 2, 2, 2, 2, 2},
-    {0, 0, 0, 0, 0, 0, 0, 0}
-};
-
-/* 32/64-bit modrm */
-int disp32_tbl[4][8] = {
-    {0, 0, 0, 0, -1, 4, 0, 0},
-    {1, 1, 1, 1, 1, 1, 1, 1},
-    {4, 4, 4, 4, 4, 4, 4, 4},
-    {0, 0, 0, 0, 0, 0, 0, 0}
-};
-
-static inline void decode_displacement(CPUX86State *env, struct x86_decode *decode)
-{
-    int addressing_size = decode->addressing_size;
-    int mod = decode->modrm.mod;
-    int rm = decode->modrm.rm;
-    
-    decode->displacement_size = 0;
-    switch (addressing_size) {
-    case 2:
-        decode->displacement_size = disp16_tbl[mod][rm];
-        if (decode->displacement_size) {
-            decode->displacement = (uint16_t)decode_bytes(env, decode,
-                                    decode->displacement_size);
-        }
-        break;
-    case 4:
-    case 8:
-        if (-1 == disp32_tbl[mod][rm]) {
-            if (5 == decode->sib.base) {
-                decode->displacement_size = 4;
-            }
-        } else {
-            decode->displacement_size = disp32_tbl[mod][rm];
-        }
-
-        if (decode->displacement_size) {
-            decode->displacement = (uint32_t)decode_bytes(env, decode,
-                                                decode->displacement_size);
-        }
-        break;
-    }
-}
-
-static inline void decode_modrm(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->modrm.modrm = decode_byte(env, decode);
-    decode->is_modrm = true;
-
-    decode_sib(env, decode);
-    decode_displacement(env, decode);
-}
-
-static inline void decode_opcode_general(CPUX86State *env,
-                                         struct x86_decode *decode,
-                                         uint8_t opcode,
-                                         struct decode_tbl *inst_decoder)
-{
-    decode->cmd = inst_decoder->cmd;
-    if (inst_decoder->operand_size) {
-        decode->operand_size = inst_decoder->operand_size;
-    }
-    decode->flags_mask = inst_decoder->flags_mask;
-
-    if (inst_decoder->is_modrm) {
-        decode_modrm(env, decode);
-    }
-    if (inst_decoder->decode_op1) {
-        inst_decoder->decode_op1(env, decode, &decode->op[0]);
-    }
-    if (inst_decoder->decode_op2) {
-        inst_decoder->decode_op2(env, decode, &decode->op[1]);
-    }
-    if (inst_decoder->decode_op3) {
-        inst_decoder->decode_op3(env, decode, &decode->op[2]);
-    }
-    if (inst_decoder->decode_op4) {
-        inst_decoder->decode_op4(env, decode, &decode->op[3]);
-    }
-    if (inst_decoder->decode_postfix) {
-        inst_decoder->decode_postfix(env, decode);
-    }
-}
-
-static inline void decode_opcode_1(CPUX86State *env, struct x86_decode *decode,
-                                   uint8_t opcode)
-{
-    struct decode_tbl *inst_decoder = &_decode_tbl1[opcode];
-    decode_opcode_general(env, decode, opcode, inst_decoder);
-}
-
-
-static inline void decode_opcode_2(CPUX86State *env, struct x86_decode *decode,
-                                   uint8_t opcode)
-{
-    struct decode_tbl *inst_decoder = &_decode_tbl2[opcode];
-    decode_opcode_general(env, decode, opcode, inst_decoder);
-}
-
-static void decode_opcodes(CPUX86State *env, struct x86_decode *decode)
-{
-    uint8_t opcode;
-
-    opcode = decode_byte(env, decode);
-    decode->opcode[decode->opcode_len++] = opcode;
-    if (opcode != OPCODE_ESCAPE) {
-        decode_opcode_1(env, decode, opcode);
-    } else {
-        opcode = decode_byte(env, decode);
-        decode->opcode[decode->opcode_len++] = opcode;
-        decode_opcode_2(env, decode, opcode);
-    }
-}
-
-uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode)
-{
-    memset(decode, 0, sizeof(*decode));
-    decode_prefix(env, decode);
-    set_addressing_size(env, decode);
-    set_operand_size(env, decode);
-
-    decode_opcodes(env, decode);
-
-    return decode->len;
-}
-
-void init_decoder(void)
-{
-    int i;
-    
-    for (i = 0; i < ARRAY_SIZE(_decode_tbl1); i++) {
-        memcpy(&_decode_tbl1[i], &invl_inst, sizeof(invl_inst));
-    }
-    for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) {
-        memcpy(&_decode_tbl2[i], &invl_inst, sizeof(invl_inst));
-    }
-    for (i = 0; i < ARRAY_SIZE(_decode_tbl3); i++) {
-        memcpy(&_decode_tbl3[i], &invl_inst_x87, sizeof(invl_inst_x87));
-    
-    }
-    for (i = 0; i < ARRAY_SIZE(_1op_inst); i++) {
-        _decode_tbl1[_1op_inst[i].opcode] = _1op_inst[i];
-    }
-    for (i = 0; i < ARRAY_SIZE(_2op_inst); i++) {
-        _decode_tbl2[_2op_inst[i].opcode] = _2op_inst[i];
-    }
-    for (i = 0; i < ARRAY_SIZE(_x87_inst); i++) {
-        int index = ((_x87_inst[i].opcode & 0xf) << 4) |
-                    ((_x87_inst[i].modrm_mod & 1) << 3) |
-                    _x87_inst[i].modrm_reg;
-        _decode_tbl3[index] = _x87_inst[i];
-    }
-}
-
-
-const char *decode_cmd_to_string(enum x86_decode_cmd cmd)
-{
-    static const char *cmds[] = {"INVL", "PUSH", "PUSH_SEG", "POP", "POP_SEG",
-        "MOV", "MOVSX", "MOVZX", "CALL_NEAR", "CALL_NEAR_ABS_INDIRECT",
-        "CALL_FAR_ABS_INDIRECT", "CMD_CALL_FAR", "RET_NEAR", "RET_FAR", "ADD",
-        "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP", "INC", "DEC", "TST",
-        "NOT", "NEG", "JMP_NEAR", "JMP_NEAR_ABS_INDIRECT", "JMP_FAR",
-        "JMP_FAR_ABS_INDIRECT", "LEA", "JXX", "JCXZ", "SETXX", "MOV_TO_SEG",
-        "MOV_FROM_SEG", "CLI", "STI", "CLD", "STD", "STC", "CLC", "OUT", "IN",
-        "INS", "OUTS", "LIDT", "SIDT", "LGDT", "SGDT", "SMSW", "LMSW",
-        "RDTSCP", "INVLPG", "MOV_TO_CR", "MOV_FROM_CR", "MOV_TO_DR",
-        "MOV_FROM_DR", "PUSHF", "POPF", "CPUID", "ROL", "ROR", "RCL", "RCR",
-        "SHL", "SAL", "SHR", "SHRD", "SHLD", "SAR", "DIV", "IDIV", "MUL",
-        "IMUL_3", "IMUL_2", "IMUL_1", "MOVS", "CMPS", "SCAS", "LODS", "STOS",
-        "BSWAP", "XCHG", "RDTSC", "RDMSR", "WRMSR", "ENTER", "LEAVE", "BT",
-        "BTS", "BTC", "BTR", "BSF", "BSR", "IRET", "INT", "POPA", "PUSHA",
-        "CWD", "CBW", "DAS", "AAD", "AAM", "AAS", "LOOP", "SLDT", "STR", "LLDT",
-        "LTR", "VERR", "VERW", "SAHF", "LAHF", "WBINVD", "LDS", "LSS", "LES",
-        "LGS", "LFS", "CMC", "XLAT", "NOP", "CMOV", "CLTS", "XADD", "HLT",
-        "CMPXCHG8B", "CMPXCHG", "POPCNT", "FNINIT", "FLD", "FLDxx", "FNSTCW",
-        "FNSTSW", "FNSETPM", "FSAVE", "FRSTOR", "FXSAVE", "FXRSTOR", "FDIV",
-        "FMUL", "FSUB", "FADD", "EMMS", "MFENCE", "SFENCE", "LFENCE",
-        "PREFETCH", "FST", "FABS", "FUCOM", "FUCOMI", "FLDCW",
-        "FXCH", "FCHS", "FCMOV", "FRNDINT", "FXAM", "LAST"};
-    return cmds[cmd];
-}
-
-target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode,
-                               target_ulong addr, X86Seg seg)
-{
-    switch (decode->segment_override) {
-    case PREFIX_CS_SEG_OVERRIDE:
-        seg = R_CS;
-        break;
-    case PREFIX_SS_SEG_OVERRIDE:
-        seg = R_SS;
-        break;
-    case PREFIX_DS_SEG_OVERRIDE:
-        seg = R_DS;
-        break;
-    case PREFIX_ES_SEG_OVERRIDE:
-        seg = R_ES;
-        break;
-    case PREFIX_FS_SEG_OVERRIDE:
-        seg = R_FS;
-        break;
-    case PREFIX_GS_SEG_OVERRIDE:
-        seg = R_GS;
-        break;
-    default:
-        break;
-    }
-    return linear_addr_size(env_cpu(env), addr, decode->addressing_size, seg);
-}
diff --git a/target/i386/hvf/x86_decode.h b/target/i386/hvf/x86_decode.h
deleted file mode 100644 (file)
index 930d965..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2016 Veertu Inc,
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef X86_EMU_DECODE_H
-#define X86_EMU_DECODE_H
-
-#include "cpu.h"
-#include "x86.h"
-
-typedef enum x86_prefix {
-    /* group 1 */
-    PREFIX_LOCK =                  0xf0,
-    PREFIX_REPN =                  0xf2,
-    PREFIX_REP =                   0xf3,
-    /* group 2 */
-    PREFIX_CS_SEG_OVERRIDE =       0x2e,
-    PREFIX_SS_SEG_OVERRIDE =       0x36,
-    PREFIX_DS_SEG_OVERRIDE =       0x3e,
-    PREFIX_ES_SEG_OVERRIDE =       0x26,
-    PREFIX_FS_SEG_OVERRIDE =       0x64,
-    PREFIX_GS_SEG_OVERRIDE =       0x65,
-    /* group 3 */
-    PREFIX_OP_SIZE_OVERRIDE =      0x66,
-    /* group 4 */
-    PREFIX_ADDR_SIZE_OVERRIDE =    0x67,
-
-    PREFIX_REX                   = 0x40,
-} x86_prefix;
-
-enum x86_decode_cmd {
-    X86_DECODE_CMD_INVL = 0,
-    
-    X86_DECODE_CMD_PUSH,
-    X86_DECODE_CMD_PUSH_SEG,
-    X86_DECODE_CMD_POP,
-    X86_DECODE_CMD_POP_SEG,
-    X86_DECODE_CMD_MOV,
-    X86_DECODE_CMD_MOVSX,
-    X86_DECODE_CMD_MOVZX,
-    X86_DECODE_CMD_CALL_NEAR,
-    X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT,
-    X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT,
-    X86_DECODE_CMD_CALL_FAR,
-    X86_DECODE_RET_NEAR,
-    X86_DECODE_RET_FAR,
-    X86_DECODE_CMD_ADD,
-    X86_DECODE_CMD_OR,
-    X86_DECODE_CMD_ADC,
-    X86_DECODE_CMD_SBB,
-    X86_DECODE_CMD_AND,
-    X86_DECODE_CMD_SUB,
-    X86_DECODE_CMD_XOR,
-    X86_DECODE_CMD_CMP,
-    X86_DECODE_CMD_INC,
-    X86_DECODE_CMD_DEC,
-    X86_DECODE_CMD_TST,
-    X86_DECODE_CMD_NOT,
-    X86_DECODE_CMD_NEG,
-    X86_DECODE_CMD_JMP_NEAR,
-    X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT,
-    X86_DECODE_CMD_JMP_FAR,
-    X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT,
-    X86_DECODE_CMD_LEA,
-    X86_DECODE_CMD_JXX,
-    X86_DECODE_CMD_JCXZ,
-    X86_DECODE_CMD_SETXX,
-    X86_DECODE_CMD_MOV_TO_SEG,
-    X86_DECODE_CMD_MOV_FROM_SEG,
-    X86_DECODE_CMD_CLI,
-    X86_DECODE_CMD_STI,
-    X86_DECODE_CMD_CLD,
-    X86_DECODE_CMD_STD,
-    X86_DECODE_CMD_STC,
-    X86_DECODE_CMD_CLC,
-    X86_DECODE_CMD_OUT,
-    X86_DECODE_CMD_IN,
-    X86_DECODE_CMD_INS,
-    X86_DECODE_CMD_OUTS,
-    X86_DECODE_CMD_LIDT,
-    X86_DECODE_CMD_SIDT,
-    X86_DECODE_CMD_LGDT,
-    X86_DECODE_CMD_SGDT,
-    X86_DECODE_CMD_SMSW,
-    X86_DECODE_CMD_LMSW,
-    X86_DECODE_CMD_RDTSCP,
-    X86_DECODE_CMD_INVLPG,
-    X86_DECODE_CMD_MOV_TO_CR,
-    X86_DECODE_CMD_MOV_FROM_CR,
-    X86_DECODE_CMD_MOV_TO_DR,
-    X86_DECODE_CMD_MOV_FROM_DR,
-    X86_DECODE_CMD_PUSHF,
-    X86_DECODE_CMD_POPF,
-    X86_DECODE_CMD_CPUID,
-    X86_DECODE_CMD_ROL,
-    X86_DECODE_CMD_ROR,
-    X86_DECODE_CMD_RCL,
-    X86_DECODE_CMD_RCR,
-    X86_DECODE_CMD_SHL,
-    X86_DECODE_CMD_SAL,
-    X86_DECODE_CMD_SHR,
-    X86_DECODE_CMD_SHRD,
-    X86_DECODE_CMD_SHLD,
-    X86_DECODE_CMD_SAR,
-    X86_DECODE_CMD_DIV,
-    X86_DECODE_CMD_IDIV,
-    X86_DECODE_CMD_MUL,
-    X86_DECODE_CMD_IMUL_3,
-    X86_DECODE_CMD_IMUL_2,
-    X86_DECODE_CMD_IMUL_1,
-    X86_DECODE_CMD_MOVS,
-    X86_DECODE_CMD_CMPS,
-    X86_DECODE_CMD_SCAS,
-    X86_DECODE_CMD_LODS,
-    X86_DECODE_CMD_STOS,
-    X86_DECODE_CMD_BSWAP,
-    X86_DECODE_CMD_XCHG,
-    X86_DECODE_CMD_RDTSC,
-    X86_DECODE_CMD_RDMSR,
-    X86_DECODE_CMD_WRMSR,
-    X86_DECODE_CMD_ENTER,
-    X86_DECODE_CMD_LEAVE,
-    X86_DECODE_CMD_BT,
-    X86_DECODE_CMD_BTS,
-    X86_DECODE_CMD_BTC,
-    X86_DECODE_CMD_BTR,
-    X86_DECODE_CMD_BSF,
-    X86_DECODE_CMD_BSR,
-    X86_DECODE_CMD_IRET,
-    X86_DECODE_CMD_INT,
-    X86_DECODE_CMD_POPA,
-    X86_DECODE_CMD_PUSHA,
-    X86_DECODE_CMD_CWD,
-    X86_DECODE_CMD_CBW,
-    X86_DECODE_CMD_DAS,
-    X86_DECODE_CMD_AAD,
-    X86_DECODE_CMD_AAM,
-    X86_DECODE_CMD_AAS,
-    X86_DECODE_CMD_LOOP,
-    X86_DECODE_CMD_SLDT,
-    X86_DECODE_CMD_STR,
-    X86_DECODE_CMD_LLDT,
-    X86_DECODE_CMD_LTR,
-    X86_DECODE_CMD_VERR,
-    X86_DECODE_CMD_VERW,
-    X86_DECODE_CMD_SAHF,
-    X86_DECODE_CMD_LAHF,
-    X86_DECODE_CMD_WBINVD,
-    X86_DECODE_CMD_LDS,
-    X86_DECODE_CMD_LSS,
-    X86_DECODE_CMD_LES,
-    X86_DECODE_XMD_LGS,
-    X86_DECODE_CMD_LFS,
-    X86_DECODE_CMD_CMC,
-    X86_DECODE_CMD_XLAT,
-    X86_DECODE_CMD_NOP,
-    X86_DECODE_CMD_CMOV,
-    X86_DECODE_CMD_CLTS,
-    X86_DECODE_CMD_XADD,
-    X86_DECODE_CMD_HLT,
-    X86_DECODE_CMD_CMPXCHG8B,
-    X86_DECODE_CMD_CMPXCHG,
-    X86_DECODE_CMD_POPCNT,
-    
-    X86_DECODE_CMD_FNINIT,
-    X86_DECODE_CMD_FLD,
-    X86_DECODE_CMD_FLDxx,
-    X86_DECODE_CMD_FNSTCW,
-    X86_DECODE_CMD_FNSTSW,
-    X86_DECODE_CMD_FNSETPM,
-    X86_DECODE_CMD_FSAVE,
-    X86_DECODE_CMD_FRSTOR,
-    X86_DECODE_CMD_FXSAVE,
-    X86_DECODE_CMD_FXRSTOR,
-    X86_DECODE_CMD_FDIV,
-    X86_DECODE_CMD_FMUL,
-    X86_DECODE_CMD_FSUB,
-    X86_DECODE_CMD_FADD,
-    X86_DECODE_CMD_EMMS,
-    X86_DECODE_CMD_MFENCE,
-    X86_DECODE_CMD_SFENCE,
-    X86_DECODE_CMD_LFENCE,
-    X86_DECODE_CMD_PREFETCH,
-    X86_DECODE_CMD_CLFLUSH,
-    X86_DECODE_CMD_FST,
-    X86_DECODE_CMD_FABS,
-    X86_DECODE_CMD_FUCOM,
-    X86_DECODE_CMD_FUCOMI,
-    X86_DECODE_CMD_FLDCW,
-    X86_DECODE_CMD_FXCH,
-    X86_DECODE_CMD_FCHS,
-    X86_DECODE_CMD_FCMOV,
-    X86_DECODE_CMD_FRNDINT,
-    X86_DECODE_CMD_FXAM,
-
-    X86_DECODE_CMD_LAST,
-};
-
-const char *decode_cmd_to_string(enum x86_decode_cmd cmd);
-
-typedef struct x86_modrm {
-    union {
-        uint8_t modrm;
-        struct {
-            uint8_t rm:3;
-            uint8_t reg:3;
-            uint8_t mod:2;
-        };
-    };
-} __attribute__ ((__packed__)) x86_modrm;
-
-typedef struct x86_sib {
-    union {
-        uint8_t sib;
-        struct {
-            uint8_t base:3;
-            uint8_t index:3;
-            uint8_t scale:2;
-        };
-    };
-} __attribute__ ((__packed__)) x86_sib;
-
-typedef struct x86_rex {
-    union {
-        uint8_t rex;
-        struct {
-            uint8_t b:1;
-            uint8_t x:1;
-            uint8_t r:1;
-            uint8_t w:1;
-            uint8_t unused:4;
-        };
-    };
-} __attribute__ ((__packed__)) x86_rex;
-
-typedef enum x86_var_type {
-    X86_VAR_IMMEDIATE,
-    X86_VAR_OFFSET,
-    X86_VAR_REG,
-    X86_VAR_RM,
-
-    /* for floating point computations */
-    X87_VAR_REG,
-    X87_VAR_FLOATP,
-    X87_VAR_INTP,
-    X87_VAR_BYTEP,
-} x86_var_type;
-
-typedef struct x86_decode_op {
-    enum x86_var_type type;
-    int size;
-
-    int reg;
-    target_ulong val;
-
-    target_ulong ptr;
-} x86_decode_op;
-
-typedef struct x86_decode {
-    int len;
-    uint8_t opcode[4];
-    uint8_t opcode_len;
-    enum x86_decode_cmd cmd;
-    int addressing_size;
-    int operand_size;
-    int lock;
-    int rep;
-    int op_size_override;
-    int addr_size_override;
-    int segment_override;
-    int control_change_inst;
-    bool fwait;
-    bool fpop_stack;
-    bool frev;
-
-    uint32_t displacement;
-    uint8_t displacement_size;
-    struct x86_rex rex;
-    bool is_modrm;
-    bool sib_present;
-    struct x86_sib sib;
-    struct x86_modrm modrm;
-    struct x86_decode_op op[4];
-    bool is_fpu;
-    uint32_t flags_mask;
-
-} x86_decode;
-
-uint64_t sign(uint64_t val, int size);
-
-uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode);
-
-target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present,
-                         int is_extended, int size);
-target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present,
-                         int is_extended, int size);
-void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,
-                        struct x86_decode_op *op);
-target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode,
-                               target_ulong addr, enum X86Seg seg);
-
-void init_decoder(void);
-void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode,
-                          struct x86_decode_op *op);
-void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode,
-                          struct x86_decode_op *op);
-void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode,
-                          struct x86_decode_op *op);
-void set_addressing_size(CPUX86State *env, struct x86_decode *decode);
-void set_operand_size(CPUX86State *env, struct x86_decode *decode);
-
-#endif
index ce5de9834973ed4afcf11556da1e014cbdcfdb5d..24af4946cd4604edac272413201574cf6c3bb7d2 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef HVF_X86_DESCR_H
 #define HVF_X86_DESCR_H
 
-#include "x86.h"
+#include "emulate/x86.h"
 
 typedef struct vmx_segment {
     uint16_t sel;
diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c
deleted file mode 100644 (file)
index 26a4876..0000000
+++ /dev/null
@@ -1,1259 +0,0 @@
-/*
- * Copyright (C) 2016 Veertu Inc,
- * Copyright (C) 2017 Google Inc,
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/////////////////////////////////////////////////////////////////////////
-//
-//  Copyright (C) 2001-2012  The Bochs Project
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
-/////////////////////////////////////////////////////////////////////////
-
-#include "qemu/osdep.h"
-#include "panic.h"
-#include "x86_decode.h"
-#include "x86.h"
-#include "x86_emu.h"
-#include "x86_flags.h"
-
-#define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \
-{                                                       \
-    fetch_operands(env, decode, 2, true, true, false);  \
-    switch (decode->operand_size) {                     \
-    case 1:                                         \
-    {                                               \
-        uint8_t v1 = (uint8_t)decode->op[0].val;    \
-        uint8_t v2 = (uint8_t)decode->op[1].val;    \
-        uint8_t diff = v1 cmd v2;                   \
-        if (save_res) {                              \
-            write_val_ext(env, decode->op[0].ptr, diff, 1);  \
-        } \
-        FLAGS_FUNC##8(env, v1, v2, diff);           \
-        break;                                      \
-    }                                               \
-    case 2:                                        \
-    {                                               \
-        uint16_t v1 = (uint16_t)decode->op[0].val;  \
-        uint16_t v2 = (uint16_t)decode->op[1].val;  \
-        uint16_t diff = v1 cmd v2;                  \
-        if (save_res) {                              \
-            write_val_ext(env, decode->op[0].ptr, diff, 2); \
-        } \
-        FLAGS_FUNC##16(env, v1, v2, diff);          \
-        break;                                      \
-    }                                               \
-    case 4:                                        \
-    {                                               \
-        uint32_t v1 = (uint32_t)decode->op[0].val;  \
-        uint32_t v2 = (uint32_t)decode->op[1].val;  \
-        uint32_t diff = v1 cmd v2;                  \
-        if (save_res) {                              \
-            write_val_ext(env, decode->op[0].ptr, diff, 4); \
-        } \
-        FLAGS_FUNC##32(env, v1, v2, diff);          \
-        break;                                      \
-    }                                               \
-    default:                                        \
-        VM_PANIC("bad size\n");                    \
-    }                                                   \
-}                                                       \
-
-target_ulong read_reg(CPUX86State *env, int reg, int size)
-{
-    switch (size) {
-    case 1:
-        return x86_reg(env, reg)->lx;
-    case 2:
-        return x86_reg(env, reg)->rx;
-    case 4:
-        return x86_reg(env, reg)->erx;
-    case 8:
-        return x86_reg(env, reg)->rrx;
-    default:
-        abort();
-    }
-    return 0;
-}
-
-void write_reg(CPUX86State *env, int reg, target_ulong val, int size)
-{
-    switch (size) {
-    case 1:
-        x86_reg(env, reg)->lx = val;
-        break;
-    case 2:
-        x86_reg(env, reg)->rx = val;
-        break;
-    case 4:
-        x86_reg(env, reg)->rrx = (uint32_t)val;
-        break;
-    case 8:
-        x86_reg(env, reg)->rrx = val;
-        break;
-    default:
-        abort();
-    }
-}
-
-target_ulong read_val_from_reg(target_ulong reg_ptr, int size)
-{
-    target_ulong val;
-    
-    switch (size) {
-    case 1:
-        val = *(uint8_t *)reg_ptr;
-        break;
-    case 2:
-        val = *(uint16_t *)reg_ptr;
-        break;
-    case 4:
-        val = *(uint32_t *)reg_ptr;
-        break;
-    case 8:
-        val = *(uint64_t *)reg_ptr;
-        break;
-    default:
-        abort();
-    }
-    return val;
-}
-
-void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size)
-{
-    switch (size) {
-    case 1:
-        *(uint8_t *)reg_ptr = val;
-        break;
-    case 2:
-        *(uint16_t *)reg_ptr = val;
-        break;
-    case 4:
-        *(uint64_t *)reg_ptr = (uint32_t)val;
-        break;
-    case 8:
-        *(uint64_t *)reg_ptr = val;
-        break;
-    default:
-        abort();
-    }
-}
-
-static bool is_host_reg(CPUX86State *env, target_ulong ptr)
-{
-    return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs);
-}
-
-void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
-{
-    if (is_host_reg(env, ptr)) {
-        write_val_to_reg(ptr, val, size);
-        return;
-    }
-    emul_ops->write_mem(env_cpu(env), &val, ptr, size);
-}
-
-uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
-{
-    emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
-    return env->emu_mmio_buf;
-}
-
-
-target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size)
-{
-    target_ulong val;
-    uint8_t *mmio_ptr;
-
-    if (is_host_reg(env, ptr)) {
-        return read_val_from_reg(ptr, size);
-    }
-
-    mmio_ptr = read_mmio(env, ptr, size);
-    switch (size) {
-    case 1:
-        val = *(uint8_t *)mmio_ptr;
-        break;
-    case 2:
-        val = *(uint16_t *)mmio_ptr;
-        break;
-    case 4:
-        val = *(uint32_t *)mmio_ptr;
-        break;
-    case 8:
-        val = *(uint64_t *)mmio_ptr;
-        break;
-    default:
-        VM_PANIC("bad size\n");
-        break;
-    }
-    return val;
-}
-
-static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
-                           int n, bool val_op0, bool val_op1, bool val_op2)
-{
-    int i;
-    bool calc_val[3] = {val_op0, val_op1, val_op2};
-
-    for (i = 0; i < n; i++) {
-        switch (decode->op[i].type) {
-        case X86_VAR_IMMEDIATE:
-            break;
-        case X86_VAR_REG:
-            VM_PANIC_ON(!decode->op[i].ptr);
-            if (calc_val[i]) {
-                decode->op[i].val = read_val_from_reg(decode->op[i].ptr,
-                                                      decode->operand_size);
-            }
-            break;
-        case X86_VAR_RM:
-            calc_modrm_operand(env, decode, &decode->op[i]);
-            if (calc_val[i]) {
-                decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
-                                                 decode->operand_size);
-            }
-            break;
-        case X86_VAR_OFFSET:
-            decode->op[i].ptr = decode_linear_addr(env, decode,
-                                                   decode->op[i].ptr,
-                                                   R_DS);
-            if (calc_val[i]) {
-                decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
-                                                 decode->operand_size);
-            }
-            break;
-        default:
-            break;
-        }
-    }
-}
-
-static void exec_mov(CPUX86State *env, struct x86_decode *decode)
-{
-    fetch_operands(env, decode, 2, false, true, false);
-    write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
-                  decode->operand_size);
-
-    env->eip += decode->len;
-}
-
-static void exec_add(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
-    env->eip += decode->len;
-}
-
-static void exec_or(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true);
-    env->eip += decode->len;
-}
-
-static void exec_adc(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true);
-    env->eip += decode->len;
-}
-
-static void exec_sbb(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true);
-    env->eip += decode->len;
-}
-
-static void exec_and(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true);
-    env->eip += decode->len;
-}
-
-static void exec_sub(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true);
-    env->eip += decode->len;
-}
-
-static void exec_xor(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true);
-    env->eip += decode->len;
-}
-
-static void exec_neg(CPUX86State *env, struct x86_decode *decode)
-{
-    /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/
-    int32_t val;
-    fetch_operands(env, decode, 2, true, true, false);
-
-    val = 0 - sign(decode->op[1].val, decode->operand_size);
-    write_val_ext(env, decode->op[1].ptr, val, decode->operand_size);
-
-    if (4 == decode->operand_size) {
-        SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val);
-    } else if (2 == decode->operand_size) {
-        SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val);
-    } else if (1 == decode->operand_size) {
-        SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val);
-    } else {
-        VM_PANIC("bad op size\n");
-    }
-
-    /*lflags_to_rflags(env);*/
-    env->eip += decode->len;
-}
-
-static void exec_cmp(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
-    env->eip += decode->len;
-}
-
-static void exec_inc(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[1].type = X86_VAR_IMMEDIATE;
-    decode->op[1].val = 0;
-
-    EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true);
-
-    env->eip += decode->len;
-}
-
-static void exec_dec(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[1].type = X86_VAR_IMMEDIATE;
-    decode->op[1].val = 0;
-
-    EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true);
-    env->eip += decode->len;
-}
-
-static void exec_tst(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false);
-    env->eip += decode->len;
-}
-
-static void exec_not(CPUX86State *env, struct x86_decode *decode)
-{
-    fetch_operands(env, decode, 1, true, false, false);
-
-    write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val,
-                  decode->operand_size);
-    env->eip += decode->len;
-}
-
-void exec_movzx(CPUX86State *env, struct x86_decode *decode)
-{
-    int src_op_size;
-    int op_size = decode->operand_size;
-
-    fetch_operands(env, decode, 1, false, false, false);
-
-    if (0xb6 == decode->opcode[1]) {
-        src_op_size = 1;
-    } else {
-        src_op_size = 2;
-    }
-    decode->operand_size = src_op_size;
-    calc_modrm_operand(env, decode, &decode->op[1]);
-    decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size);
-    write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
-
-    env->eip += decode->len;
-}
-
-static void exec_out(CPUX86State *env, struct x86_decode *decode)
-{
-    switch (decode->opcode[0]) {
-    case 0xe6:
-        emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1);
-        break;
-    case 0xe7:
-        emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1,
-                            decode->operand_size, 1);
-        break;
-    case 0xee:
-        emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1);
-        break;
-    case 0xef:
-        emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1,
-                            decode->operand_size, 1);
-        break;
-    default:
-        VM_PANIC("Bad out opcode\n");
-        break;
-    }
-    env->eip += decode->len;
-}
-
-static void exec_in(CPUX86State *env, struct x86_decode *decode)
-{
-    target_ulong val = 0;
-    switch (decode->opcode[0]) {
-    case 0xe4:
-        emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1);
-        break;
-    case 0xe5:
-        emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0,
-                      decode->operand_size, 1);
-        if (decode->operand_size == 2) {
-            AX(env) = val;
-        } else {
-            RAX(env) = (uint32_t)val;
-        }
-        break;
-    case 0xec:
-        emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1);
-        break;
-    case 0xed:
-        emul_ops->handle_io(env_cpu(env), DX(env), &val, 0,
-                            decode->operand_size, 1);
-        if (decode->operand_size == 2) {
-            AX(env) = val;
-        } else {
-            RAX(env) = (uint32_t)val;
-        }
-
-        break;
-    default:
-        VM_PANIC("Bad in opcode\n");
-        break;
-    }
-
-    env->eip += decode->len;
-}
-
-static inline void string_increment_reg(CPUX86State *env, int reg,
-                                        struct x86_decode *decode)
-{
-    target_ulong val = read_reg(env, reg, decode->addressing_size);
-    if (env->eflags & DF_MASK) {
-        val -= decode->operand_size;
-    } else {
-        val += decode->operand_size;
-    }
-    write_reg(env, reg, val, decode->addressing_size);
-}
-
-static inline void string_rep(CPUX86State *env, struct x86_decode *decode,
-                              void (*func)(CPUX86State *env,
-                                           struct x86_decode *ins), int rep)
-{
-    target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size);
-    while (rcx--) {
-        func(env, decode);
-        write_reg(env, R_ECX, rcx, decode->addressing_size);
-        if ((PREFIX_REP == rep) && !get_ZF(env)) {
-            break;
-        }
-        if ((PREFIX_REPN == rep) && get_ZF(env)) {
-            break;
-        }
-    }
-}
-
-static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
-{
-    target_ulong addr = linear_addr_size(env_cpu(env), RDI(env),
-                                         decode->addressing_size, R_ES);
-
-    emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0,
-                        decode->operand_size, 1);
-    emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr,
-                        decode->operand_size);
-
-    string_increment_reg(env, R_EDI, decode);
-}
-
-static void exec_ins(CPUX86State *env, struct x86_decode *decode)
-{
-    if (decode->rep) {
-        string_rep(env, decode, exec_ins_single, 0);
-    } else {
-        exec_ins_single(env, decode);
-    }
-
-    env->eip += decode->len;
-}
-
-static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
-{
-    target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
-
-    emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr,
-                       decode->operand_size);
-    emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1,
-                        decode->operand_size, 1);
-
-    string_increment_reg(env, R_ESI, decode);
-}
-
-static void exec_outs(CPUX86State *env, struct x86_decode *decode)
-{
-    if (decode->rep) {
-        string_rep(env, decode, exec_outs_single, 0);
-    } else {
-        exec_outs_single(env, decode);
-    }
-
-    env->eip += decode->len;
-}
-
-static void exec_movs_single(CPUX86State *env, struct x86_decode *decode)
-{
-    target_ulong src_addr;
-    target_ulong dst_addr;
-    target_ulong val;
-
-    src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
-    dst_addr = linear_addr_size(env_cpu(env), RDI(env),
-                                decode->addressing_size, R_ES);
-
-    val = read_val_ext(env, src_addr, decode->operand_size);
-    write_val_ext(env, dst_addr, val, decode->operand_size);
-
-    string_increment_reg(env, R_ESI, decode);
-    string_increment_reg(env, R_EDI, decode);
-}
-
-static void exec_movs(CPUX86State *env, struct x86_decode *decode)
-{
-    if (decode->rep) {
-        string_rep(env, decode, exec_movs_single, 0);
-    } else {
-        exec_movs_single(env, decode);
-    }
-
-    env->eip += decode->len;
-}
-
-static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode)
-{
-    target_ulong src_addr;
-    target_ulong dst_addr;
-
-    src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
-    dst_addr = linear_addr_size(env_cpu(env), RDI(env),
-                                decode->addressing_size, R_ES);
-
-    decode->op[0].type = X86_VAR_IMMEDIATE;
-    decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size);
-    decode->op[1].type = X86_VAR_IMMEDIATE;
-    decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size);
-
-    EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
-
-    string_increment_reg(env, R_ESI, decode);
-    string_increment_reg(env, R_EDI, decode);
-}
-
-static void exec_cmps(CPUX86State *env, struct x86_decode *decode)
-{
-    if (decode->rep) {
-        string_rep(env, decode, exec_cmps_single, decode->rep);
-    } else {
-        exec_cmps_single(env, decode);
-    }
-    env->eip += decode->len;
-}
-
-
-static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
-{
-    target_ulong addr;
-    target_ulong val;
-
-    addr = linear_addr_size(env_cpu(env), RDI(env),
-                            decode->addressing_size, R_ES);
-    val = read_reg(env, R_EAX, decode->operand_size);
-    emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size);
-
-    string_increment_reg(env, R_EDI, decode);
-}
-
-
-static void exec_stos(CPUX86State *env, struct x86_decode *decode)
-{
-    if (decode->rep) {
-        string_rep(env, decode, exec_stos_single, 0);
-    } else {
-        exec_stos_single(env, decode);
-    }
-
-    env->eip += decode->len;
-}
-
-static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
-{
-    target_ulong addr;
-
-    addr = linear_addr_size(env_cpu(env), RDI(env),
-                            decode->addressing_size, R_ES);
-    decode->op[1].type = X86_VAR_IMMEDIATE;
-    emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
-
-    EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
-    string_increment_reg(env, R_EDI, decode);
-}
-
-static void exec_scas(CPUX86State *env, struct x86_decode *decode)
-{
-    decode->op[0].type = X86_VAR_REG;
-    decode->op[0].reg = R_EAX;
-    if (decode->rep) {
-        string_rep(env, decode, exec_scas_single, decode->rep);
-    } else {
-        exec_scas_single(env, decode);
-    }
-
-    env->eip += decode->len;
-}
-
-static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
-{
-    target_ulong addr;
-    target_ulong val = 0;
-
-    addr = decode_linear_addr(env, decode, RSI(env), R_DS);
-    emul_ops->read_mem(env_cpu(env), &val, addr,  decode->operand_size);
-    write_reg(env, R_EAX, val, decode->operand_size);
-
-    string_increment_reg(env, R_ESI, decode);
-}
-
-static void exec_lods(CPUX86State *env, struct x86_decode *decode)
-{
-    if (decode->rep) {
-        string_rep(env, decode, exec_lods_single, 0);
-    } else {
-        exec_lods_single(env, decode);
-    }
-
-    env->eip += decode->len;
-}
-
-void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code)
-{
-    env->exception_nr = exception_index;
-    env->error_code = error_code;
-    env->has_error_code = true;
-    env->exception_injected = 1;
-}
-
-static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode)
-{
-    emul_ops->simulate_rdmsr(env_cpu(env));
-    env->eip += decode->len;
-}
-
-static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode)
-{
-    emul_ops->simulate_wrmsr(env_cpu(env));
-    env->eip += decode->len;
-}
-
-/*
- * flag:
- * 0 - bt, 1 - btc, 2 - bts, 3 - btr
- */
-static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
-{
-    int32_t displacement;
-    uint8_t index;
-    bool cf;
-    int mask = (4 == decode->operand_size) ? 0x1f : 0xf;
-
-    VM_PANIC_ON(decode->rex.rex);
-
-    fetch_operands(env, decode, 2, false, true, false);
-    index = decode->op[1].val & mask;
-
-    if (decode->op[0].type != X86_VAR_REG) {
-        if (4 == decode->operand_size) {
-            displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32;
-            decode->op[0].ptr += 4 * displacement;
-        } else if (2 == decode->operand_size) {
-            displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16;
-            decode->op[0].ptr += 2 * displacement;
-        } else {
-            VM_PANIC("bt 64bit\n");
-        }
-    }
-    decode->op[0].val = read_val_ext(env, decode->op[0].ptr,
-                                     decode->operand_size);
-    cf = (decode->op[0].val >> index) & 0x01;
-
-    switch (flag) {
-    case 0:
-        set_CF(env, cf);
-        return;
-    case 1:
-        decode->op[0].val ^= (1u << index);
-        break;
-    case 2:
-        decode->op[0].val |= (1u << index);
-        break;
-    case 3:
-        decode->op[0].val &= ~(1u << index);
-        break;
-    }
-    write_val_ext(env, decode->op[0].ptr, decode->op[0].val,
-                  decode->operand_size);
-    set_CF(env, cf);
-}
-
-static void exec_bt(CPUX86State *env, struct x86_decode *decode)
-{
-    do_bt(env, decode, 0);
-    env->eip += decode->len;
-}
-
-static void exec_btc(CPUX86State *env, struct x86_decode *decode)
-{
-    do_bt(env, decode, 1);
-    env->eip += decode->len;
-}
-
-static void exec_btr(CPUX86State *env, struct x86_decode *decode)
-{
-    do_bt(env, decode, 3);
-    env->eip += decode->len;
-}
-
-static void exec_bts(CPUX86State *env, struct x86_decode *decode)
-{
-    do_bt(env, decode, 2);
-    env->eip += decode->len;
-}
-
-void exec_shl(CPUX86State *env, struct x86_decode *decode)
-{
-    uint8_t count;
-    int of = 0, cf = 0;
-
-    fetch_operands(env, decode, 2, true, true, false);
-
-    count = decode->op[1].val;
-    count &= 0x1f;      /* count is masked to 5 bits*/
-    if (!count) {
-        goto exit;
-    }
-
-    switch (decode->operand_size) {
-    case 1:
-    {
-        uint8_t res = 0;
-        if (count <= 8) {
-            res = (decode->op[0].val << count);
-            cf = (decode->op[0].val >> (8 - count)) & 0x1;
-            of = cf ^ (res >> 7);
-        }
-
-        write_val_ext(env, decode->op[0].ptr, res, 1);
-        SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res);
-        SET_FLAGS_OxxxxC(env, of, cf);
-        break;
-    }
-    case 2:
-    {
-        uint16_t res = 0;
-
-        /* from bochs */
-        if (count <= 16) {
-            res = (decode->op[0].val << count);
-            cf = (decode->op[0].val >> (16 - count)) & 0x1;
-            of = cf ^ (res >> 15); /* of = cf ^ result15 */
-        }
-
-        write_val_ext(env, decode->op[0].ptr, res, 2);
-        SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res);
-        SET_FLAGS_OxxxxC(env, of, cf);
-        break;
-    }
-    case 4:
-    {
-        uint32_t res = decode->op[0].val << count;
-
-        write_val_ext(env, decode->op[0].ptr, res, 4);
-        SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res);
-        cf = (decode->op[0].val >> (32 - count)) & 0x1;
-        of = cf ^ (res >> 31); /* of = cf ^ result31 */
-        SET_FLAGS_OxxxxC(env, of, cf);
-        break;
-    }
-    default:
-        abort();
-    }
-
-exit:
-    /* lflags_to_rflags(env); */
-    env->eip += decode->len;
-}
-
-void exec_movsx(CPUX86State *env, struct x86_decode *decode)
-{
-    int src_op_size;
-    int op_size = decode->operand_size;
-
-    fetch_operands(env, decode, 2, false, false, false);
-
-    if (0xbe == decode->opcode[1]) {
-        src_op_size = 1;
-    } else {
-        src_op_size = 2;
-    }
-
-    decode->operand_size = src_op_size;
-    calc_modrm_operand(env, decode, &decode->op[1]);
-    decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size),
-                             src_op_size);
-
-    write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
-
-    env->eip += decode->len;
-}
-
-void exec_ror(CPUX86State *env, struct x86_decode *decode)
-{
-    uint8_t count;
-
-    fetch_operands(env, decode, 2, true, true, false);
-    count = decode->op[1].val;
-
-    switch (decode->operand_size) {
-    case 1:
-    {
-        uint32_t bit6, bit7;
-        uint8_t res;
-
-        if ((count & 0x07) == 0) {
-            if (count & 0x18) {
-                bit6 = ((uint8_t)decode->op[0].val >> 6) & 1;
-                bit7 = ((uint8_t)decode->op[0].val >> 7) & 1;
-                SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
-             }
-        } else {
-            count &= 0x7; /* use only bottom 3 bits */
-            res = ((uint8_t)decode->op[0].val >> count) |
-                   ((uint8_t)decode->op[0].val << (8 - count));
-            write_val_ext(env, decode->op[0].ptr, res, 1);
-            bit6 = (res >> 6) & 1;
-            bit7 = (res >> 7) & 1;
-            /* set eflags: ROR count affects the following flags: C, O */
-            SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
-        }
-        break;
-    }
-    case 2:
-    {
-        uint32_t bit14, bit15;
-        uint16_t res;
-
-        if ((count & 0x0f) == 0) {
-            if (count & 0x10) {
-                bit14 = ((uint16_t)decode->op[0].val >> 14) & 1;
-                bit15 = ((uint16_t)decode->op[0].val >> 15) & 1;
-                /* of = result14 ^ result15 */
-                SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
-            }
-        } else {
-            count &= 0x0f;  /* use only 4 LSB's */
-            res = ((uint16_t)decode->op[0].val >> count) |
-                   ((uint16_t)decode->op[0].val << (16 - count));
-            write_val_ext(env, decode->op[0].ptr, res, 2);
-
-            bit14 = (res >> 14) & 1;
-            bit15 = (res >> 15) & 1;
-            /* of = result14 ^ result15 */
-            SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
-        }
-        break;
-    }
-    case 4:
-    {
-        uint32_t bit31, bit30;
-        uint32_t res;
-
-        count &= 0x1f;
-        if (count) {
-            res = ((uint32_t)decode->op[0].val >> count) |
-                   ((uint32_t)decode->op[0].val << (32 - count));
-            write_val_ext(env, decode->op[0].ptr, res, 4);
-
-            bit31 = (res >> 31) & 1;
-            bit30 = (res >> 30) & 1;
-            /* of = result30 ^ result31 */
-            SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31);
-        }
-        break;
-        }
-    }
-    env->eip += decode->len;
-}
-
-void exec_rol(CPUX86State *env, struct x86_decode *decode)
-{
-    uint8_t count;
-
-    fetch_operands(env, decode, 2, true, true, false);
-    count = decode->op[1].val;
-
-    switch (decode->operand_size) {
-    case 1:
-    {
-        uint32_t bit0, bit7;
-        uint8_t res;
-
-        if ((count & 0x07) == 0) {
-            if (count & 0x18) {
-                bit0 = ((uint8_t)decode->op[0].val & 1);
-                bit7 = ((uint8_t)decode->op[0].val >> 7);
-                SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
-            }
-        }  else {
-            count &= 0x7; /* use only lowest 3 bits */
-            res = ((uint8_t)decode->op[0].val << count) |
-                   ((uint8_t)decode->op[0].val >> (8 - count));
-
-            write_val_ext(env, decode->op[0].ptr, res, 1);
-            /* set eflags:
-             * ROL count affects the following flags: C, O
-             */
-            bit0 = (res &  1);
-            bit7 = (res >> 7);
-            SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
-        }
-        break;
-    }
-    case 2:
-    {
-        uint32_t bit0, bit15;
-        uint16_t res;
-
-        if ((count & 0x0f) == 0) {
-            if (count & 0x10) {
-                bit0  = ((uint16_t)decode->op[0].val & 0x1);
-                bit15 = ((uint16_t)decode->op[0].val >> 15);
-                /* of = cf ^ result15 */
-                SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
-            }
-        } else {
-            count &= 0x0f; /* only use bottom 4 bits */
-            res = ((uint16_t)decode->op[0].val << count) |
-                   ((uint16_t)decode->op[0].val >> (16 - count));
-
-            write_val_ext(env, decode->op[0].ptr, res, 2);
-            bit0  = (res & 0x1);
-            bit15 = (res >> 15);
-            /* of = cf ^ result15 */
-            SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
-        }
-        break;
-    }
-    case 4:
-    {
-        uint32_t bit0, bit31;
-        uint32_t res;
-
-        count &= 0x1f;
-        if (count) {
-            res = ((uint32_t)decode->op[0].val << count) |
-                   ((uint32_t)decode->op[0].val >> (32 - count));
-
-            write_val_ext(env, decode->op[0].ptr, res, 4);
-            bit0  = (res & 0x1);
-            bit31 = (res >> 31);
-            /* of = cf ^ result31 */
-            SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0);
-        }
-        break;
-        }
-    }
-    env->eip += decode->len;
-}
-
-
-void exec_rcl(CPUX86State *env, struct x86_decode *decode)
-{
-    uint8_t count;
-    int of = 0, cf = 0;
-
-    fetch_operands(env, decode, 2, true, true, false);
-    count = decode->op[1].val & 0x1f;
-
-    switch (decode->operand_size) {
-    case 1:
-    {
-        uint8_t op1_8 = decode->op[0].val;
-        uint8_t res;
-        count %= 9;
-        if (!count) {
-            break;
-        }
-
-        if (1 == count) {
-            res = (op1_8 << 1) | get_CF(env);
-        } else {
-            res = (op1_8 << count) | (get_CF(env) << (count - 1)) |
-                   (op1_8 >> (9 - count));
-        }
-
-        write_val_ext(env, decode->op[0].ptr, res, 1);
-
-        cf = (op1_8 >> (8 - count)) & 0x01;
-        of = cf ^ (res >> 7); /* of = cf ^ result7 */
-        SET_FLAGS_OxxxxC(env, of, cf);
-        break;
-    }
-    case 2:
-    {
-        uint16_t res;
-        uint16_t op1_16 = decode->op[0].val;
-
-        count %= 17;
-        if (!count) {
-            break;
-        }
-
-        if (1 == count) {
-            res = (op1_16 << 1) | get_CF(env);
-        } else if (count == 16) {
-            res = (get_CF(env) << 15) | (op1_16 >> 1);
-        } else { /* 2..15 */
-            res = (op1_16 << count) | (get_CF(env) << (count - 1)) |
-                   (op1_16 >> (17 - count));
-        }
-
-        write_val_ext(env, decode->op[0].ptr, res, 2);
-
-        cf = (op1_16 >> (16 - count)) & 0x1;
-        of = cf ^ (res >> 15); /* of = cf ^ result15 */
-        SET_FLAGS_OxxxxC(env, of, cf);
-        break;
-    }
-    case 4:
-    {
-        uint32_t res;
-        uint32_t op1_32 = decode->op[0].val;
-
-        if (!count) {
-            break;
-        }
-
-        if (1 == count) {
-            res = (op1_32 << 1) | get_CF(env);
-        } else {
-            res = (op1_32 << count) | (get_CF(env) << (count - 1)) |
-                   (op1_32 >> (33 - count));
-        }
-
-        write_val_ext(env, decode->op[0].ptr, res, 4);
-
-        cf = (op1_32 >> (32 - count)) & 0x1;
-        of = cf ^ (res >> 31); /* of = cf ^ result31 */
-        SET_FLAGS_OxxxxC(env, of, cf);
-        break;
-        }
-    }
-    env->eip += decode->len;
-}
-
-void exec_rcr(CPUX86State *env, struct x86_decode *decode)
-{
-    uint8_t count;
-    int of = 0, cf = 0;
-
-    fetch_operands(env, decode, 2, true, true, false);
-    count = decode->op[1].val & 0x1f;
-
-    switch (decode->operand_size) {
-    case 1:
-    {
-        uint8_t op1_8 = decode->op[0].val;
-        uint8_t res;
-
-        count %= 9;
-        if (!count) {
-            break;
-        }
-        res = (op1_8 >> count) | (get_CF(env) << (8 - count)) |
-               (op1_8 << (9 - count));
-
-        write_val_ext(env, decode->op[0].ptr, res, 1);
-
-        cf = (op1_8 >> (count - 1)) & 0x1;
-        of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */
-        SET_FLAGS_OxxxxC(env, of, cf);
-        break;
-    }
-    case 2:
-    {
-        uint16_t op1_16 = decode->op[0].val;
-        uint16_t res;
-
-        count %= 17;
-        if (!count) {
-            break;
-        }
-        res = (op1_16 >> count) | (get_CF(env) << (16 - count)) |
-               (op1_16 << (17 - count));
-
-        write_val_ext(env, decode->op[0].ptr, res, 2);
-
-        cf = (op1_16 >> (count - 1)) & 0x1;
-        of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^
-                                                            result14 */
-        SET_FLAGS_OxxxxC(env, of, cf);
-        break;
-    }
-    case 4:
-    {
-        uint32_t res;
-        uint32_t op1_32 = decode->op[0].val;
-
-        if (!count) {
-            break;
-        }
-
-        if (1 == count) {
-            res = (op1_32 >> 1) | (get_CF(env) << 31);
-        } else {
-            res = (op1_32 >> count) | (get_CF(env) << (32 - count)) |
-                   (op1_32 << (33 - count));
-        }
-
-        write_val_ext(env, decode->op[0].ptr, res, 4);
-
-        cf = (op1_32 >> (count - 1)) & 0x1;
-        of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */
-        SET_FLAGS_OxxxxC(env, of, cf);
-        break;
-        }
-    }
-    env->eip += decode->len;
-}
-
-static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
-{
-    fetch_operands(env, decode, 2, true, true, false);
-
-    write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
-                  decode->operand_size);
-    write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
-                  decode->operand_size);
-
-    env->eip += decode->len;
-}
-
-static void exec_xadd(CPUX86State *env, struct x86_decode *decode)
-{
-    EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
-    write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
-                  decode->operand_size);
-
-    env->eip += decode->len;
-}
-
-static struct cmd_handler {
-    enum x86_decode_cmd cmd;
-    void (*handler)(CPUX86State *env, struct x86_decode *ins);
-} handlers[] = {
-    {X86_DECODE_CMD_INVL, NULL,},
-    {X86_DECODE_CMD_MOV, exec_mov},
-    {X86_DECODE_CMD_ADD, exec_add},
-    {X86_DECODE_CMD_OR, exec_or},
-    {X86_DECODE_CMD_ADC, exec_adc},
-    {X86_DECODE_CMD_SBB, exec_sbb},
-    {X86_DECODE_CMD_AND, exec_and},
-    {X86_DECODE_CMD_SUB, exec_sub},
-    {X86_DECODE_CMD_NEG, exec_neg},
-    {X86_DECODE_CMD_XOR, exec_xor},
-    {X86_DECODE_CMD_CMP, exec_cmp},
-    {X86_DECODE_CMD_INC, exec_inc},
-    {X86_DECODE_CMD_DEC, exec_dec},
-    {X86_DECODE_CMD_TST, exec_tst},
-    {X86_DECODE_CMD_NOT, exec_not},
-    {X86_DECODE_CMD_MOVZX, exec_movzx},
-    {X86_DECODE_CMD_OUT, exec_out},
-    {X86_DECODE_CMD_IN, exec_in},
-    {X86_DECODE_CMD_INS, exec_ins},
-    {X86_DECODE_CMD_OUTS, exec_outs},
-    {X86_DECODE_CMD_RDMSR, exec_rdmsr},
-    {X86_DECODE_CMD_WRMSR, exec_wrmsr},
-    {X86_DECODE_CMD_BT, exec_bt},
-    {X86_DECODE_CMD_BTR, exec_btr},
-    {X86_DECODE_CMD_BTC, exec_btc},
-    {X86_DECODE_CMD_BTS, exec_bts},
-    {X86_DECODE_CMD_SHL, exec_shl},
-    {X86_DECODE_CMD_ROL, exec_rol},
-    {X86_DECODE_CMD_ROR, exec_ror},
-    {X86_DECODE_CMD_RCR, exec_rcr},
-    {X86_DECODE_CMD_RCL, exec_rcl},
-    /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/
-    {X86_DECODE_CMD_MOVS, exec_movs},
-    {X86_DECODE_CMD_CMPS, exec_cmps},
-    {X86_DECODE_CMD_STOS, exec_stos},
-    {X86_DECODE_CMD_SCAS, exec_scas},
-    {X86_DECODE_CMD_LODS, exec_lods},
-    {X86_DECODE_CMD_MOVSX, exec_movsx},
-    {X86_DECODE_CMD_XCHG, exec_xchg},
-    {X86_DECODE_CMD_XADD, exec_xadd},
-};
-
-static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
-
-const struct x86_emul_ops *emul_ops;
-
-static void init_cmd_handler(void)
-{
-    int i;
-    for (i = 0; i < ARRAY_SIZE(handlers); i++) {
-        _cmd_handler[handlers[i].cmd] = handlers[i];
-    }
-}
-
-bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
-{
-    if (!_cmd_handler[ins->cmd].handler) {
-        printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip,
-                ins->cmd, ins->opcode[0],
-                ins->opcode_len > 1 ? ins->opcode[1] : 0);
-        env->eip += ins->len;
-        return true;
-    }
-
-    _cmd_handler[ins->cmd].handler(env, ins);
-    return true;
-}
-
-void init_emu(const struct x86_emul_ops *o)
-{
-    emul_ops = o;
-    init_cmd_handler();
-}
diff --git a/target/i386/hvf/x86_emu.h b/target/i386/hvf/x86_emu.h
deleted file mode 100644 (file)
index 555b567..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2016 Veertu Inc,
- * Copyright (C) 2017 Google Inc,
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef X86_EMU_H
-#define X86_EMU_H
-
-#include "x86.h"
-#include "x86_decode.h"
-#include "cpu.h"
-
-struct x86_emul_ops {
-    void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
-    void (*write_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
-    void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc,
-                                    enum X86Seg seg);
-    void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction,
-                      int size, int count);
-    void (*simulate_rdmsr)(CPUState *cs);
-    void (*simulate_wrmsr)(CPUState *cs);
-};
-
-extern const struct x86_emul_ops *emul_ops;
-
-void init_emu(const struct x86_emul_ops *ops);
-bool exec_instruction(CPUX86State *env, struct x86_decode *ins);
-void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code);
-
-target_ulong read_reg(CPUX86State *env, int reg, int size);
-void write_reg(CPUX86State *env, int reg, target_ulong val, int size);
-target_ulong read_val_from_reg(target_ulong reg_ptr, int size);
-void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size);
-void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size);
-uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes);
-target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size);
-
-void exec_movzx(CPUX86State *env, struct x86_decode *decode);
-void exec_shl(CPUX86State *env, struct x86_decode *decode);
-void exec_movsx(CPUX86State *env, struct x86_decode *decode);
-void exec_ror(CPUX86State *env, struct x86_decode *decode);
-void exec_rol(CPUX86State *env, struct x86_decode *decode);
-void exec_rcl(CPUX86State *env, struct x86_decode *decode);
-void exec_rcr(CPUX86State *env, struct x86_decode *decode);
-#endif
diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c
deleted file mode 100644 (file)
index 84e2736..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-//
-//  Copyright (C) 2001-2012  The Bochs Project
-//  Copyright (C) 2017 Google Inc.
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
-/////////////////////////////////////////////////////////////////////////
-/*
- * flags functions
- */
-
-#include "qemu/osdep.h"
-
-#include "panic.h"
-#include "cpu.h"
-#include "x86_flags.h"
-#include "x86.h"
-
-
-/* this is basically bocsh code */
-
-#define LF_SIGN_BIT     31
-
-#define LF_BIT_SD      (0)          /* lazy Sign Flag Delta            */
-#define LF_BIT_AF      (3)          /* lazy Adjust flag                */
-#define LF_BIT_PDB     (8)          /* lazy Parity Delta Byte (8 bits) */
-#define LF_BIT_CF      (31)         /* lazy Carry Flag                 */
-#define LF_BIT_PO      (30)         /* lazy Partial Overflow = CF ^ OF */
-
-#define LF_MASK_SD     (0x01 << LF_BIT_SD)
-#define LF_MASK_AF     (0x01 << LF_BIT_AF)
-#define LF_MASK_PDB    (0xFF << LF_BIT_PDB)
-#define LF_MASK_CF     (0x01 << LF_BIT_CF)
-#define LF_MASK_PO     (0x01 << LF_BIT_PO)
-
-/* ******************* */
-/* OSZAPC */
-/* ******************* */
-
-/* size, carries, result */
-#define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \
-    target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
-    (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
-    env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \
-    if ((size) == 32) { \
-        temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
-    } else if ((size) == 16) { \
-        temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
-    } else if ((size) == 8)  { \
-        temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
-    } else { \
-        VM_PANIC("unimplemented");  \
-    } \
-    env->lflags.auxbits = (target_ulong)(uint32_t)temp; \
-}
-
-/* carries, result */
-#define SET_FLAGS_OSZAPC_8(carries, result) \
-    SET_FLAGS_OSZAPC_SIZE(8, carries, result)
-#define SET_FLAGS_OSZAPC_16(carries, result) \
-    SET_FLAGS_OSZAPC_SIZE(16, carries, result)
-#define SET_FLAGS_OSZAPC_32(carries, result) \
-    SET_FLAGS_OSZAPC_SIZE(32, carries, result)
-
-/* ******************* */
-/* OSZAP */
-/* ******************* */
-/* size, carries, result */
-#define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \
-    target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
-    (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
-    if ((size) == 32) { \
-        temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
-    } else if ((size) == 16) { \
-        temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
-    } else if ((size) == 8) { \
-        temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
-    } else { \
-        VM_PANIC("unimplemented");      \
-    } \
-    env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \
-    target_ulong delta_c = (env->lflags.auxbits ^ temp) & LF_MASK_CF; \
-    delta_c ^= (delta_c >> 1); \
-    env->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \
-}
-
-/* carries, result */
-#define SET_FLAGS_OSZAP_8(carries, result) \
-    SET_FLAGS_OSZAP_SIZE(8, carries, result)
-#define SET_FLAGS_OSZAP_16(carries, result) \
-    SET_FLAGS_OSZAP_SIZE(16, carries, result)
-#define SET_FLAGS_OSZAP_32(carries, result) \
-    SET_FLAGS_OSZAP_SIZE(32, carries, result)
-
-void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf)
-{
-    uint32_t temp_po = new_of ^ new_cf;
-    env->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF);
-    env->lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF);
-}
-
-void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                            uint32_t diff)
-{
-    SET_FLAGS_OSZAPC_32(SUB_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                            uint16_t diff)
-{
-    SET_FLAGS_OSZAPC_16(SUB_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                            uint8_t diff)
-{
-    SET_FLAGS_OSZAPC_8(SUB_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                            uint32_t diff)
-{
-    SET_FLAGS_OSZAPC_32(ADD_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                            uint16_t diff)
-{
-    SET_FLAGS_OSZAPC_16(ADD_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                            uint8_t diff)
-{
-    SET_FLAGS_OSZAPC_8(ADD_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                            uint32_t diff)
-{
-    SET_FLAGS_OSZAP_32(SUB_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                            uint16_t diff)
-{
-    SET_FLAGS_OSZAP_16(SUB_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                            uint8_t diff)
-{
-    SET_FLAGS_OSZAP_8(SUB_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                            uint32_t diff)
-{
-    SET_FLAGS_OSZAP_32(ADD_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                            uint16_t diff)
-{
-    SET_FLAGS_OSZAP_16(ADD_COUT_VEC(v1, v2, diff), diff);
-}
-
-void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                            uint8_t diff)
-{
-    SET_FLAGS_OSZAP_8(ADD_COUT_VEC(v1, v2, diff), diff);
-}
-
-
-void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                              uint32_t diff)
-{
-    SET_FLAGS_OSZAPC_32(0, diff);
-}
-
-void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                              uint16_t diff)
-{
-    SET_FLAGS_OSZAPC_16(0, diff);
-}
-
-void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                             uint8_t diff)
-{
-    SET_FLAGS_OSZAPC_8(0, diff);
-}
-
-bool get_PF(CPUX86State *env)
-{
-    uint32_t temp = (255 & env->lflags.result);
-    temp = temp ^ (255 & (env->lflags.auxbits >> LF_BIT_PDB));
-    temp = (temp ^ (temp >> 4)) & 0x0F;
-    return (0x9669U >> temp) & 1;
-}
-
-void set_PF(CPUX86State *env, bool val)
-{
-    uint32_t temp = (255 & env->lflags.result) ^ (!val);
-    env->lflags.auxbits &= ~(LF_MASK_PDB);
-    env->lflags.auxbits |= (temp << LF_BIT_PDB);
-}
-
-bool get_OF(CPUX86State *env)
-{
-    return ((env->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1;
-}
-
-bool get_CF(CPUX86State *env)
-{
-    return (env->lflags.auxbits >> LF_BIT_CF) & 1;
-}
-
-void set_OF(CPUX86State *env, bool val)
-{
-    bool old_cf = get_CF(env);
-    SET_FLAGS_OxxxxC(env, val, old_cf);
-}
-
-void set_CF(CPUX86State *env, bool val)
-{
-    bool old_of = get_OF(env);
-    SET_FLAGS_OxxxxC(env, old_of, val);
-}
-
-bool get_AF(CPUX86State *env)
-{
-    return (env->lflags.auxbits >> LF_BIT_AF) & 1;
-}
-
-void set_AF(CPUX86State *env, bool val)
-{
-    env->lflags.auxbits &= ~(LF_MASK_AF);
-    env->lflags.auxbits |= val << LF_BIT_AF;
-}
-
-bool get_ZF(CPUX86State *env)
-{
-    return !env->lflags.result;
-}
-
-void set_ZF(CPUX86State *env, bool val)
-{
-    if (val) {
-        env->lflags.auxbits ^=
-         (((env->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD);
-        /* merge the parity bits into the Parity Delta Byte */
-        uint32_t temp_pdb = (255 & env->lflags.result);
-        env->lflags.auxbits ^= (temp_pdb << LF_BIT_PDB);
-        /* now zero the .result value */
-        env->lflags.result = 0;
-    } else {
-        env->lflags.result |= (1 << 8);
-    }
-}
-
-bool get_SF(CPUX86State *env)
-{
-    return ((env->lflags.result >> LF_SIGN_BIT) ^
-            (env->lflags.auxbits >> LF_BIT_SD)) & 1;
-}
-
-void set_SF(CPUX86State *env, bool val)
-{
-    bool temp_sf = get_SF(env);
-    env->lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD;
-}
-
-void lflags_to_rflags(CPUX86State *env)
-{
-    env->eflags &= ~(CC_C|CC_P|CC_A|CC_Z|CC_S|CC_O);
-    env->eflags |= get_CF(env) ? CC_C : 0;
-    env->eflags |= get_PF(env) ? CC_P : 0;
-    env->eflags |= get_AF(env) ? CC_A : 0;
-    env->eflags |= get_ZF(env) ? CC_Z : 0;
-    env->eflags |= get_SF(env) ? CC_S : 0;
-    env->eflags |= get_OF(env) ? CC_O : 0;
-}
-
-void rflags_to_lflags(CPUX86State *env)
-{
-    env->lflags.auxbits = env->lflags.result = 0;
-    set_OF(env, env->eflags & CC_O);
-    set_SF(env, env->eflags & CC_S);
-    set_ZF(env, env->eflags & CC_Z);
-    set_AF(env, env->eflags & CC_A);
-    set_PF(env, env->eflags & CC_P);
-    set_CF(env, env->eflags & CC_C);
-}
diff --git a/target/i386/hvf/x86_flags.h b/target/i386/hvf/x86_flags.h
deleted file mode 100644 (file)
index 6c17500..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-//
-//  Copyright (C) 2001-2012  The Bochs Project
-//  Copyright (C) 2017 Google Inc.
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
-/////////////////////////////////////////////////////////////////////////
-/*
- * x86 eflags functions
- */
-
-#ifndef X86_EMU_FLAGS_H
-#define X86_EMU_FLAGS_H
-
-#include "cpu.h"
-void lflags_to_rflags(CPUX86State *env);
-void rflags_to_lflags(CPUX86State *env);
-
-bool get_PF(CPUX86State *env);
-void set_PF(CPUX86State *env, bool val);
-bool get_CF(CPUX86State *env);
-void set_CF(CPUX86State *env, bool val);
-bool get_AF(CPUX86State *env);
-void set_AF(CPUX86State *env, bool val);
-bool get_ZF(CPUX86State *env);
-void set_ZF(CPUX86State *env, bool val);
-bool get_SF(CPUX86State *env);
-void set_SF(CPUX86State *env, bool val);
-bool get_OF(CPUX86State *env);
-void set_OF(CPUX86State *env, bool val);
-
-void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf);
-
-void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                            uint32_t diff);
-void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                            uint16_t diff);
-void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                           uint8_t diff);
-
-void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                            uint32_t diff);
-void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                            uint16_t diff);
-void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                           uint8_t diff);
-
-void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                           uint32_t diff);
-void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                           uint16_t diff);
-void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                          uint8_t diff);
-
-void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                           uint32_t diff);
-void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                           uint16_t diff);
-void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                          uint8_t diff);
-
-void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2,
-                              uint32_t diff);
-void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2,
-                              uint16_t diff);
-void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2,
-                             uint8_t diff);
-
-#endif /* X86_EMU_FLAGS_H */
index 579d0c3a4cc58f843d409ec14693f1c3f9564287..afc5c17d5d5c2c7fdce2584b177551f5f20b58e7 100644 (file)
@@ -19,7 +19,7 @@
 #include "qemu/osdep.h"
 #include "panic.h"
 #include "cpu.h"
-#include "x86.h"
+#include "emulate/x86.h"
 #include "x86_mmu.h"
 #include "vmcs.h"
 #include "vmx.h"
index 161217991fc0d5f519f74ce76881de03d2ea41d1..bdf8b51ae67076ecb2159c89a5eb8af5657a0064 100644 (file)
 #include "hvf-i386.h"
 #include "vmcs.h"
 #include "vmx.h"
-#include "x86.h"
+#include "emulate/x86.h"
 #include "x86_descr.h"
 #include "x86_mmu.h"
-#include "x86_decode.h"
-#include "x86_emu.h"
+#include "emulate/x86_decode.h"
+#include "emulate/x86_emu.h"
 #include "x86_task.h"
 #include "x86hvf.h"
 
index 531a340b37c9a38498f6203bdf1f9f05c9d1a31e..2057314892a90c178b263e17869c7e9590f0fa1c 100644 (file)
@@ -24,7 +24,7 @@
 #include "vmcs.h"
 #include "cpu.h"
 #include "x86_descr.h"
-#include "x86_decode.h"
+#include "emulate/x86_decode.h"
 #include "system/hw_accel.h"
 
 #include "hw/i386/apic_internal.h"