[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH RFC 1/9] xen: Emulate with no writes; compute current instruction length


  • To: xen-devel@xxxxxxxxxxxxx
  • From: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx>
  • Date: Wed, 2 Jul 2014 16:33:53 +0300
  • Cc: tim@xxxxxxx, Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx>
  • Comment: DomainKeys? See http://domainkeys.sourceforge.net/
  • Delivery-date: Wed, 02 Jul 2014 13:34:32 +0000
  • Domainkey-signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=bitdefender.com; b=gsL8Q+htqbxDGTHB6pwj7fbp4rP/u02c9273RlNJ/ACMYUr2VdnQtl3/xlKoPxiXBbd5R2IDDIAxVHbmYY1jpbbgnrv52sFbP2JzVWPMRQWj50TmjiODLLaZPffpJdTY3EYagt5jr26Ys9l50H6Eibva8pf8/S8dVvFl2WaRfPpW/gtS47RiCOvwBEVvChCLo79XHyNQhoM0EdSQgktN31AZBOsvcMGBAwA3Tb5bgzKs2/DzKcieZq7BDyYtek/GXk4YiR33xxiD129dEN2D8v+GffKjGu1m+7ye4mE1J9MoQR1VTqRPdYp5/1Mdt3E2nFyeQVNhqe5xp1GEKv50qQ==; h=Received:Received:Received:Received:From:To:Cc:Subject:Date:Message-Id:X-Mailer:X-BitDefender-Scanner:X-BitDefender-Spam:X-BitDefender-SpamStamp:X-BitDefender-CF-Stamp;
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>

Added support for emulating an instruction with no memory writes and
for retrieving the length of the next instruction. Additionally,
introduced hvm_emulate_one_full(bool_t nowrite), which acts upon all
possible return values from the hvm_emulate_one() functions (RETRY,
EXCEPTION, UNHANDLEABLE).

Signed-off-by: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx>
---
 xen/arch/x86/Makefile             |    2 +
 xen/arch/x86/hvm/emulate.c        |  192 +++++++
 xen/arch/x86/inat-tables.c        | 1130 +++++++++++++++++++++++++++++++++++++
 xen/arch/x86/inat.c               |   96 ++++
 xen/arch/x86/insn.c               |  576 +++++++++++++++++++
 xen/include/asm-x86/hvm/emulate.h |    5 +
 xen/include/asm-x86/inat.h        |  221 ++++++++
 xen/include/asm-x86/inat_types.h  |   29 +
 xen/include/asm-x86/insn.h        |  199 +++++++
 9 files changed, 2450 insertions(+)
 create mode 100644 xen/arch/x86/inat-tables.c
 create mode 100644 xen/arch/x86/inat.c
 create mode 100644 xen/arch/x86/insn.c
 create mode 100644 xen/include/asm-x86/inat.h
 create mode 100644 xen/include/asm-x86/inat_types.h
 create mode 100644 xen/include/asm-x86/insn.h

diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 6c90b1b..30829a0 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -59,6 +59,8 @@ obj-y += crash.o
 obj-y += tboot.o
 obj-y += hpet.o
 obj-y += xstate.o
+obj-y += insn.o
+obj-y += inat.o
 
 obj-$(crash_debug) += gdbstub.o
 
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index eac159f..1dc8c67 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -21,6 +21,7 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/trace.h>
 #include <asm/hvm/support.h>
+#include <asm/insn.h>
 
 static void hvmtrace_io_assist(int is_mmio, ioreq_t *p)
 {
@@ -688,6 +689,17 @@ static int hvmemul_write(
     return X86EMUL_OKAY;
 }
 
+static int hvmemul_write_dummy(
+    enum x86_segment __attribute__((unused)) seg,
+    unsigned long __attribute__((unused)) offset,
+    void __attribute__((unused)) *p_data,
+    unsigned int __attribute__((unused)) bytes,
+    struct x86_emulate_ctxt __attribute__((unused)) *ctxt)
+{
+    /* discarding the write */
+    return X86EMUL_OKAY;
+}
+
 static int hvmemul_cmpxchg(
     enum x86_segment seg,
     unsigned long offset,
@@ -1239,6 +1251,139 @@ int hvm_emulate_one(
     return X86EMUL_OKAY;
 }
 
+int hvm_emulate_one_no_write(
+    struct hvm_emulate_ctxt *hvmemul_ctxt)
+{
+    struct cpu_user_regs *regs = hvmemul_ctxt->ctxt.regs;
+    struct vcpu *curr = current;
+    uint32_t new_intr_shadow, pfec = PFEC_page_present;
+    struct hvm_vcpu_io *vio = &curr->arch.hvm_vcpu.hvm_io;
+    struct x86_emulate_ops local_ops = hvm_emulate_ops;
+    unsigned long addr;
+    int rc;
+
+    if ( hvm_long_mode_enabled(curr) &&
+         hvmemul_ctxt->seg_reg[x86_seg_cs].attr.fields.l )
+    {
+        hvmemul_ctxt->ctxt.addr_size = hvmemul_ctxt->ctxt.sp_size = 64;
+    }
+    else
+    {
+        hvmemul_ctxt->ctxt.addr_size =
+            hvmemul_ctxt->seg_reg[x86_seg_cs].attr.fields.db ? 32 : 16;
+        hvmemul_ctxt->ctxt.sp_size =
+            hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16;
+    }
+
+    if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl == 3 )
+        pfec |= PFEC_user_mode;
+
+    hvmemul_ctxt->insn_buf_eip = regs->eip;
+    if ( !vio->mmio_insn_bytes )
+    {
+        hvmemul_ctxt->insn_buf_bytes =
+            hvm_get_insn_bytes(curr, hvmemul_ctxt->insn_buf) ?:
+            (hvm_virtual_to_linear_addr(x86_seg_cs,
+                                        &hvmemul_ctxt->seg_reg[x86_seg_cs],
+                                        regs->eip,
+                                        sizeof(hvmemul_ctxt->insn_buf),
+                                        hvm_access_insn_fetch,
+                                        hvmemul_ctxt->ctxt.addr_size,
+                                        &addr) &&
+             hvm_fetch_from_guest_virt_nofault(hvmemul_ctxt->insn_buf, addr,
+                                               sizeof(hvmemul_ctxt->insn_buf),
+                                               pfec) == HVMCOPY_okay) ?
+            sizeof(hvmemul_ctxt->insn_buf) : 0;
+    }
+    else
+    {
+        hvmemul_ctxt->insn_buf_bytes = vio->mmio_insn_bytes;
+        memcpy(hvmemul_ctxt->insn_buf, vio->mmio_insn, vio->mmio_insn_bytes);
+    }
+
+    hvmemul_ctxt->exn_pending = 0;
+    vio->mmio_retrying = vio->mmio_retry;
+    vio->mmio_retry = 0;
+
+    local_ops.write = hvmemul_write_dummy;
+    rc = x86_emulate(&hvmemul_ctxt->ctxt, &local_ops);
+
+    if ( rc == X86EMUL_OKAY && vio->mmio_retry )
+        rc = X86EMUL_RETRY;
+    if ( rc != X86EMUL_RETRY )
+    {
+        vio->mmio_large_read_bytes = vio->mmio_large_write_bytes = 0;
+        vio->mmio_insn_bytes = 0;
+    }
+    else
+    {
+        BUILD_BUG_ON(sizeof(vio->mmio_insn) < sizeof(hvmemul_ctxt->insn_buf));
+        vio->mmio_insn_bytes = hvmemul_ctxt->insn_buf_bytes;
+        memcpy(vio->mmio_insn, hvmemul_ctxt->insn_buf, vio->mmio_insn_bytes);
+    }
+
+    if ( rc != X86EMUL_OKAY )
+        return rc;
+
+    new_intr_shadow = hvmemul_ctxt->intr_shadow;
+
+    /* MOV-SS instruction toggles MOV-SS shadow, else we just clear it. */
+    if ( hvmemul_ctxt->ctxt.retire.flags.mov_ss )
+        new_intr_shadow ^= HVM_INTR_SHADOW_MOV_SS;
+    else
+        new_intr_shadow &= ~HVM_INTR_SHADOW_MOV_SS;
+
+    /* STI instruction toggles STI shadow, else we just clear it. */
+    if ( hvmemul_ctxt->ctxt.retire.flags.sti )
+        new_intr_shadow ^= HVM_INTR_SHADOW_STI;
+    else
+        new_intr_shadow &= ~HVM_INTR_SHADOW_STI;
+
+    if ( hvmemul_ctxt->intr_shadow != new_intr_shadow )
+    {
+        hvmemul_ctxt->intr_shadow = new_intr_shadow;
+        hvm_funcs.set_interrupt_shadow(curr, new_intr_shadow);
+    }
+
+    if ( hvmemul_ctxt->ctxt.retire.flags.hlt &&
+         !hvm_local_events_need_delivery(curr) )
+    {
+        hvm_hlt(regs->eflags);
+    }
+
+    return X86EMUL_OKAY;
+}
+
+void hvm_emulate_one_full(bool_t nowrite)
+{
+    struct hvm_emulate_ctxt ctx[1] = {};
+    int rc = X86EMUL_RETRY;
+
+    hvm_emulate_prepare(ctx, guest_cpu_user_regs());
+
+    while ( rc == X86EMUL_RETRY )
+    {
+        if ( nowrite )
+            rc = hvm_emulate_one_no_write(ctx);
+        else
+            rc = hvm_emulate_one(ctx);
+    }
+
+    switch ( rc )
+    {
+    case X86EMUL_UNHANDLEABLE:
+        hvm_inject_hw_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);
+        break;
+    case X86EMUL_EXCEPTION:
+        if ( ctx->exn_pending )
+            hvm_inject_hw_exception(ctx->exn_vector, ctx->exn_error_code);
+        /* fall through */
+    default:
+        hvm_emulate_writeback(ctx);
+        break;
+    }
+}
+
 void hvm_emulate_prepare(
     struct hvm_emulate_ctxt *hvmemul_ctxt,
     struct cpu_user_regs *regs)
@@ -1278,6 +1423,53 @@ struct segment_register *hvmemul_get_seg_reg(
     return &hvmemul_ctxt->seg_reg[seg];
 }
 
+int hvm_get_insn_length(
+    struct hvm_emulate_ctxt *hvmemul_ctxt)
+{
+    struct cpu_user_regs *regs = hvmemul_ctxt->ctxt.regs;
+    struct vcpu *curr = current;
+    uint32_t pfec = PFEC_page_present;
+    unsigned long addr;
+    struct x86_emulate_ops local_ops = hvm_emulate_ops;
+    struct insn insn;
+
+    local_ops.write = hvmemul_write_dummy;
+
+    if ( hvm_long_mode_enabled(curr) &&
+        hvmemul_ctxt->seg_reg[x86_seg_cs].attr.fields.l )
+        hvmemul_ctxt->ctxt.addr_size = hvmemul_ctxt->ctxt.sp_size = 64;
+    else
+    {
+        hvmemul_ctxt->ctxt.addr_size =
+            hvmemul_ctxt->seg_reg[x86_seg_cs].attr.fields.db ? 32 : 16;
+        hvmemul_ctxt->ctxt.sp_size =
+            hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16;
+    }
+
+    if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl == 3 )
+        pfec |= PFEC_user_mode;
+
+    hvmemul_ctxt->insn_buf_eip = regs->eip;
+    hvmemul_ctxt->insn_buf_bytes =
+        hvm_get_insn_bytes(curr, hvmemul_ctxt->insn_buf)
+        ? :
+        (hvm_virtual_to_linear_addr(
+            x86_seg_cs, &hvmemul_ctxt->seg_reg[x86_seg_cs],
+            regs->eip, sizeof(hvmemul_ctxt->insn_buf),
+            hvm_access_insn_fetch, hvmemul_ctxt->ctxt.addr_size, &addr) &&
+        !hvm_fetch_from_guest_virt_nofault(
+            hvmemul_ctxt->insn_buf, addr,
+            sizeof(hvmemul_ctxt->insn_buf), pfec))
+    ? sizeof(hvmemul_ctxt->insn_buf) : 0;
+
+    hvmemul_ctxt->exn_pending = 0;
+
+    insn_init(&insn, hvmemul_ctxt->insn_buf, hvm_long_mode_enabled(curr));
+    insn_get_length(&insn);
+
+    return insn.length;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/x86/inat-tables.c b/xen/arch/x86/inat-tables.c
new file mode 100644
index 0000000..39252c3
--- /dev/null
+++ b/xen/arch/x86/inat-tables.c
@@ -0,0 +1,1130 @@
+/* x86 opcode map generated from x86-opcode-map.txt */
+/* Do not change this code. */
+
+/* Table: one byte opcode */
+const insn_attr_t inat_primary_table[INAT_OPCODE_TABLE_SIZE] = {
+       [0x00] = INAT_MODRM,
+       [0x01] = INAT_MODRM,
+       [0x02] = INAT_MODRM,
+       [0x03] = INAT_MODRM,
+       [0x04] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x05] = INAT_MAKE_IMM(INAT_IMM_VWORD32),
+       [0x08] = INAT_MODRM,
+       [0x09] = INAT_MODRM,
+       [0x0a] = INAT_MODRM,
+       [0x0b] = INAT_MODRM,
+       [0x0c] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x0d] = INAT_MAKE_IMM(INAT_IMM_VWORD32),
+       [0x0f] = INAT_MAKE_ESCAPE(1),
+       [0x10] = INAT_MODRM,
+       [0x11] = INAT_MODRM,
+       [0x12] = INAT_MODRM,
+       [0x13] = INAT_MODRM,
+       [0x14] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x15] = INAT_MAKE_IMM(INAT_IMM_VWORD32),
+       [0x18] = INAT_MODRM,
+       [0x19] = INAT_MODRM,
+       [0x1a] = INAT_MODRM,
+       [0x1b] = INAT_MODRM,
+       [0x1c] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x1d] = INAT_MAKE_IMM(INAT_IMM_VWORD32),
+       [0x20] = INAT_MODRM,
+       [0x21] = INAT_MODRM,
+       [0x22] = INAT_MODRM,
+       [0x23] = INAT_MODRM,
+       [0x24] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x25] = INAT_MAKE_IMM(INAT_IMM_VWORD32),
+       [0x26] = INAT_MAKE_PREFIX(INAT_PFX_ES),
+       [0x28] = INAT_MODRM,
+       [0x29] = INAT_MODRM,
+       [0x2a] = INAT_MODRM,
+       [0x2b] = INAT_MODRM,
+       [0x2c] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x2d] = INAT_MAKE_IMM(INAT_IMM_VWORD32),
+       [0x2e] = INAT_MAKE_PREFIX(INAT_PFX_CS),
+       [0x30] = INAT_MODRM,
+       [0x31] = INAT_MODRM,
+       [0x32] = INAT_MODRM,
+       [0x33] = INAT_MODRM,
+       [0x34] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x35] = INAT_MAKE_IMM(INAT_IMM_VWORD32),
+       [0x36] = INAT_MAKE_PREFIX(INAT_PFX_SS),
+       [0x38] = INAT_MODRM,
+       [0x39] = INAT_MODRM,
+       [0x3a] = INAT_MODRM,
+       [0x3b] = INAT_MODRM,
+       [0x3c] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x3d] = INAT_MAKE_IMM(INAT_IMM_VWORD32),
+       [0x3e] = INAT_MAKE_PREFIX(INAT_PFX_DS),
+       [0x40] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x41] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x42] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x43] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x44] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x45] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x46] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x47] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x48] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x49] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x4a] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x4b] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x4c] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x4d] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x4e] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x4f] = INAT_MAKE_PREFIX(INAT_PFX_REX),
+       [0x50] = INAT_FORCE64,
+       [0x51] = INAT_FORCE64,
+       [0x52] = INAT_FORCE64,
+       [0x53] = INAT_FORCE64,
+       [0x54] = INAT_FORCE64,
+       [0x55] = INAT_FORCE64,
+       [0x56] = INAT_FORCE64,
+       [0x57] = INAT_FORCE64,
+       [0x58] = INAT_FORCE64,
+       [0x59] = INAT_FORCE64,
+       [0x5a] = INAT_FORCE64,
+       [0x5b] = INAT_FORCE64,
+       [0x5c] = INAT_FORCE64,
+       [0x5d] = INAT_FORCE64,
+       [0x5e] = INAT_FORCE64,
+       [0x5f] = INAT_FORCE64,
+       [0x62] = INAT_MODRM,
+       [0x63] = INAT_MODRM | INAT_MODRM,
+       [0x64] = INAT_MAKE_PREFIX(INAT_PFX_FS),
+       [0x65] = INAT_MAKE_PREFIX(INAT_PFX_GS),
+       [0x66] = INAT_MAKE_PREFIX(INAT_PFX_OPNDSZ),
+       [0x67] = INAT_MAKE_PREFIX(INAT_PFX_ADDRSZ),
+       [0x68] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x69] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM,
+       [0x6a] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64,
+       [0x6b] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM,
+       [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x71] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x72] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x73] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x74] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x75] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x76] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x77] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x78] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x79] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x7a] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x7b] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x7c] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x7d] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x7e] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x7f] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0x80] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(1),
+       [0x81] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM | 
INAT_MAKE_GROUP(1),
+       [0x82] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(1),
+       [0x83] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(1),
+       [0x84] = INAT_MODRM,
+       [0x85] = INAT_MODRM,
+       [0x86] = INAT_MODRM,
+       [0x87] = INAT_MODRM,
+       [0x88] = INAT_MODRM,
+       [0x89] = INAT_MODRM,
+       [0x8a] = INAT_MODRM,
+       [0x8b] = INAT_MODRM,
+       [0x8c] = INAT_MODRM,
+       [0x8d] = INAT_MODRM,
+       [0x8e] = INAT_MODRM,
+       [0x8f] = INAT_MAKE_GROUP(2) | INAT_MODRM | INAT_FORCE64,
+       [0x9a] = INAT_MAKE_IMM(INAT_IMM_PTR),
+       [0x9c] = INAT_FORCE64,
+       [0x9d] = INAT_FORCE64,
+       [0xa0] = INAT_MOFFSET,
+       [0xa1] = INAT_MOFFSET,
+       [0xa2] = INAT_MOFFSET,
+       [0xa3] = INAT_MOFFSET,
+       [0xa8] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xa9] = INAT_MAKE_IMM(INAT_IMM_VWORD32),
+       [0xb0] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xb1] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xb2] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xb3] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xb4] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xb5] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xb6] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xb7] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xb8] = INAT_MAKE_IMM(INAT_IMM_VWORD),
+       [0xb9] = INAT_MAKE_IMM(INAT_IMM_VWORD),
+       [0xba] = INAT_MAKE_IMM(INAT_IMM_VWORD),
+       [0xbb] = INAT_MAKE_IMM(INAT_IMM_VWORD),
+       [0xbc] = INAT_MAKE_IMM(INAT_IMM_VWORD),
+       [0xbd] = INAT_MAKE_IMM(INAT_IMM_VWORD),
+       [0xbe] = INAT_MAKE_IMM(INAT_IMM_VWORD),
+       [0xbf] = INAT_MAKE_IMM(INAT_IMM_VWORD),
+       [0xc0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(3),
+       [0xc1] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(3),
+       [0xc2] = INAT_MAKE_IMM(INAT_IMM_WORD) | INAT_FORCE64,
+       [0xc4] = INAT_MODRM | INAT_MAKE_PREFIX(INAT_PFX_VEX3),
+       [0xc5] = INAT_MODRM | INAT_MAKE_PREFIX(INAT_PFX_VEX2),
+       [0xc6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(4),
+       [0xc7] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM | 
INAT_MAKE_GROUP(4),
+       [0xc8] = INAT_MAKE_IMM(INAT_IMM_WORD) | INAT_SCNDIMM,
+       [0xc9] = INAT_FORCE64,
+       [0xca] = INAT_MAKE_IMM(INAT_IMM_WORD),
+       [0xcd] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xd0] = INAT_MODRM | INAT_MAKE_GROUP(3),
+       [0xd1] = INAT_MODRM | INAT_MAKE_GROUP(3),
+       [0xd2] = INAT_MODRM | INAT_MAKE_GROUP(3),
+       [0xd3] = INAT_MODRM | INAT_MAKE_GROUP(3),
+       [0xd4] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xd5] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xd8] = INAT_MODRM,
+       [0xd9] = INAT_MODRM,
+       [0xda] = INAT_MODRM,
+       [0xdb] = INAT_MODRM,
+       [0xdc] = INAT_MODRM,
+       [0xdd] = INAT_MODRM,
+       [0xde] = INAT_MODRM,
+       [0xdf] = INAT_MODRM,
+       [0xe0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64,
+       [0xe1] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64,
+       [0xe2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64,
+       [0xe3] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64,
+       [0xe4] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xe5] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xe6] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xe7] = INAT_MAKE_IMM(INAT_IMM_BYTE),
+       [0xe8] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0xe9] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0xea] = INAT_MAKE_IMM(INAT_IMM_PTR),
+       [0xeb] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64,
+       [0xf0] = INAT_MAKE_PREFIX(INAT_PFX_LOCK),
+       [0xf2] = INAT_MAKE_PREFIX(INAT_PFX_REPNE),
+       [0xf3] = INAT_MAKE_PREFIX(INAT_PFX_REPE),
+       [0xf6] = INAT_MODRM | INAT_MAKE_GROUP(5),
+       [0xf7] = INAT_MODRM | INAT_MAKE_GROUP(6),
+       [0xfe] = INAT_MAKE_GROUP(7),
+       [0xff] = INAT_MAKE_GROUP(8),
+};
+
+/* Table: 2-byte opcode (0x0f) */
+const insn_attr_t inat_escape_table_1[INAT_OPCODE_TABLE_SIZE] = {
+       [0x00] = INAT_MAKE_GROUP(9),
+       [0x01] = INAT_MAKE_GROUP(10),
+       [0x02] = INAT_MODRM,
+       [0x03] = INAT_MODRM,
+       [0x0d] = INAT_MODRM | INAT_MAKE_GROUP(11),
+       [0x0f] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM,
+       [0x10] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x11] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x12] = INAT_MODRM | INAT_VEXOK | INAT_MODRM | INAT_VEXOK | 
INAT_VARIANT,
+       [0x13] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x14] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x15] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x16] = INAT_MODRM | INAT_VEXOK | INAT_MODRM | INAT_VEXOK | 
INAT_VARIANT,
+       [0x17] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x18] = INAT_MAKE_GROUP(12),
+       [0x1f] = INAT_MODRM,
+       [0x20] = INAT_MODRM,
+       [0x21] = INAT_MODRM,
+       [0x22] = INAT_MODRM,
+       [0x23] = INAT_MODRM,
+       [0x28] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x29] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x2a] = INAT_MODRM | INAT_VARIANT,
+       [0x2b] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x2c] = INAT_MODRM | INAT_VARIANT,
+       [0x2d] = INAT_MODRM | INAT_VARIANT,
+       [0x2e] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x2f] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x38] = INAT_MAKE_ESCAPE(2),
+       [0x3a] = INAT_MAKE_ESCAPE(3),
+       [0x40] = INAT_MODRM,
+       [0x41] = INAT_MODRM,
+       [0x42] = INAT_MODRM,
+       [0x43] = INAT_MODRM,
+       [0x44] = INAT_MODRM,
+       [0x45] = INAT_MODRM,
+       [0x46] = INAT_MODRM,
+       [0x47] = INAT_MODRM,
+       [0x48] = INAT_MODRM,
+       [0x49] = INAT_MODRM,
+       [0x4a] = INAT_MODRM,
+       [0x4b] = INAT_MODRM,
+       [0x4c] = INAT_MODRM,
+       [0x4d] = INAT_MODRM,
+       [0x4e] = INAT_MODRM,
+       [0x4f] = INAT_MODRM,
+       [0x50] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x51] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x52] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x53] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x54] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x55] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x56] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x57] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x58] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x59] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x5a] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x5b] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x5c] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x5d] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x5e] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x5f] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x60] = INAT_MODRM | INAT_VARIANT,
+       [0x61] = INAT_MODRM | INAT_VARIANT,
+       [0x62] = INAT_MODRM | INAT_VARIANT,
+       [0x63] = INAT_MODRM | INAT_VARIANT,
+       [0x64] = INAT_MODRM | INAT_VARIANT,
+       [0x65] = INAT_MODRM | INAT_VARIANT,
+       [0x66] = INAT_MODRM | INAT_VARIANT,
+       [0x67] = INAT_MODRM | INAT_VARIANT,
+       [0x68] = INAT_MODRM | INAT_VARIANT,
+       [0x69] = INAT_MODRM | INAT_VARIANT,
+       [0x6a] = INAT_MODRM | INAT_VARIANT,
+       [0x6b] = INAT_MODRM | INAT_VARIANT,
+       [0x6c] = INAT_VARIANT,
+       [0x6d] = INAT_VARIANT,
+       [0x6e] = INAT_MODRM | INAT_VARIANT,
+       [0x6f] = INAT_MODRM | INAT_VARIANT,
+       [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0x71] = INAT_MAKE_GROUP(13),
+       [0x72] = INAT_MAKE_GROUP(14),
+       [0x73] = INAT_MAKE_GROUP(15),
+       [0x74] = INAT_MODRM | INAT_VARIANT,
+       [0x75] = INAT_MODRM | INAT_VARIANT,
+       [0x76] = INAT_MODRM | INAT_VARIANT,
+       [0x77] = INAT_VEXOK | INAT_VEXOK,
+       [0x78] = INAT_MODRM,
+       [0x79] = INAT_MODRM,
+       [0x7c] = INAT_VARIANT,
+       [0x7d] = INAT_VARIANT,
+       [0x7e] = INAT_MODRM | INAT_VARIANT,
+       [0x7f] = INAT_MODRM | INAT_VARIANT,
+       [0x80] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x81] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x82] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x83] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x84] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x85] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x86] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x87] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x88] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x89] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x8a] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x8b] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x8c] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x8d] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x8e] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x8f] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64,
+       [0x90] = INAT_MODRM,
+       [0x91] = INAT_MODRM,
+       [0x92] = INAT_MODRM,
+       [0x93] = INAT_MODRM,
+       [0x94] = INAT_MODRM,
+       [0x95] = INAT_MODRM,
+       [0x96] = INAT_MODRM,
+       [0x97] = INAT_MODRM,
+       [0x98] = INAT_MODRM,
+       [0x99] = INAT_MODRM,
+       [0x9a] = INAT_MODRM,
+       [0x9b] = INAT_MODRM,
+       [0x9c] = INAT_MODRM,
+       [0x9d] = INAT_MODRM,
+       [0x9e] = INAT_MODRM,
+       [0x9f] = INAT_MODRM,
+       [0xa0] = INAT_FORCE64,
+       [0xa1] = INAT_FORCE64,
+       [0xa3] = INAT_MODRM,
+       [0xa4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM,
+       [0xa5] = INAT_MODRM,
+       [0xa6] = INAT_MAKE_GROUP(16),
+       [0xa7] = INAT_MAKE_GROUP(17),
+       [0xa8] = INAT_FORCE64,
+       [0xa9] = INAT_FORCE64,
+       [0xab] = INAT_MODRM,
+       [0xac] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM,
+       [0xad] = INAT_MODRM,
+       [0xae] = INAT_MAKE_GROUP(18),
+       [0xaf] = INAT_MODRM,
+       [0xb0] = INAT_MODRM,
+       [0xb1] = INAT_MODRM,
+       [0xb2] = INAT_MODRM,
+       [0xb3] = INAT_MODRM,
+       [0xb4] = INAT_MODRM,
+       [0xb5] = INAT_MODRM,
+       [0xb6] = INAT_MODRM,
+       [0xb7] = INAT_MODRM,
+       [0xb8] = INAT_VARIANT,
+       [0xb9] = INAT_MAKE_GROUP(19),
+       [0xba] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | 
INAT_MAKE_GROUP(20),
+       [0xbb] = INAT_MODRM,
+       [0xbc] = INAT_MODRM | INAT_VARIANT,
+       [0xbd] = INAT_MODRM | INAT_VARIANT,
+       [0xbe] = INAT_MODRM,
+       [0xbf] = INAT_MODRM,
+       [0xc0] = INAT_MODRM,
+       [0xc1] = INAT_MODRM,
+       [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VARIANT,
+       [0xc3] = INAT_MODRM,
+       [0xc4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0xc5] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0xc6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VARIANT,
+       [0xc7] = INAT_MAKE_GROUP(21),
+       [0xd0] = INAT_VARIANT,
+       [0xd1] = INAT_MODRM | INAT_VARIANT,
+       [0xd2] = INAT_MODRM | INAT_VARIANT,
+       [0xd3] = INAT_MODRM | INAT_VARIANT,
+       [0xd4] = INAT_MODRM | INAT_VARIANT,
+       [0xd5] = INAT_MODRM | INAT_VARIANT,
+       [0xd6] = INAT_VARIANT,
+       [0xd7] = INAT_MODRM | INAT_VARIANT,
+       [0xd8] = INAT_MODRM | INAT_VARIANT,
+       [0xd9] = INAT_MODRM | INAT_VARIANT,
+       [0xda] = INAT_MODRM | INAT_VARIANT,
+       [0xdb] = INAT_MODRM | INAT_VARIANT,
+       [0xdc] = INAT_MODRM | INAT_VARIANT,
+       [0xdd] = INAT_MODRM | INAT_VARIANT,
+       [0xde] = INAT_MODRM | INAT_VARIANT,
+       [0xdf] = INAT_MODRM | INAT_VARIANT,
+       [0xe0] = INAT_MODRM | INAT_VARIANT,
+       [0xe1] = INAT_MODRM | INAT_VARIANT,
+       [0xe2] = INAT_MODRM | INAT_VARIANT,
+       [0xe3] = INAT_MODRM | INAT_VARIANT,
+       [0xe4] = INAT_MODRM | INAT_VARIANT,
+       [0xe5] = INAT_MODRM | INAT_VARIANT,
+       [0xe6] = INAT_VARIANT,
+       [0xe7] = INAT_MODRM | INAT_VARIANT,
+       [0xe8] = INAT_MODRM | INAT_VARIANT,
+       [0xe9] = INAT_MODRM | INAT_VARIANT,
+       [0xea] = INAT_MODRM | INAT_VARIANT,
+       [0xeb] = INAT_MODRM | INAT_VARIANT,
+       [0xec] = INAT_MODRM | INAT_VARIANT,
+       [0xed] = INAT_MODRM | INAT_VARIANT,
+       [0xee] = INAT_MODRM | INAT_VARIANT,
+       [0xef] = INAT_MODRM | INAT_VARIANT,
+       [0xf0] = INAT_VARIANT,
+       [0xf1] = INAT_MODRM | INAT_VARIANT,
+       [0xf2] = INAT_MODRM | INAT_VARIANT,
+       [0xf3] = INAT_MODRM | INAT_VARIANT,
+       [0xf4] = INAT_MODRM | INAT_VARIANT,
+       [0xf5] = INAT_MODRM | INAT_VARIANT,
+       [0xf6] = INAT_MODRM | INAT_VARIANT,
+       [0xf7] = INAT_MODRM | INAT_VARIANT,
+       [0xf8] = INAT_MODRM | INAT_VARIANT,
+       [0xf9] = INAT_MODRM | INAT_VARIANT,
+       [0xfa] = INAT_MODRM | INAT_VARIANT,
+       [0xfb] = INAT_MODRM | INAT_VARIANT,
+       [0xfc] = INAT_MODRM | INAT_VARIANT,
+       [0xfd] = INAT_MODRM | INAT_VARIANT,
+       [0xfe] = INAT_MODRM | INAT_VARIANT,
+};
+const insn_attr_t inat_escape_table_1_1[INAT_OPCODE_TABLE_SIZE] = {
+       [0x10] = INAT_MODRM | INAT_VEXOK,
+       [0x11] = INAT_MODRM | INAT_VEXOK,
+       [0x12] = INAT_MODRM | INAT_VEXOK,
+       [0x13] = INAT_MODRM | INAT_VEXOK,
+       [0x14] = INAT_MODRM | INAT_VEXOK,
+       [0x15] = INAT_MODRM | INAT_VEXOK,
+       [0x16] = INAT_MODRM | INAT_VEXOK,
+       [0x17] = INAT_MODRM | INAT_VEXOK,
+       [0x28] = INAT_MODRM | INAT_VEXOK,
+       [0x29] = INAT_MODRM | INAT_VEXOK,
+       [0x2a] = INAT_MODRM,
+       [0x2b] = INAT_MODRM | INAT_VEXOK,
+       [0x2c] = INAT_MODRM,
+       [0x2d] = INAT_MODRM,
+       [0x2e] = INAT_MODRM | INAT_VEXOK,
+       [0x2f] = INAT_MODRM | INAT_VEXOK,
+       [0x50] = INAT_MODRM | INAT_VEXOK,
+       [0x51] = INAT_MODRM | INAT_VEXOK,
+       [0x54] = INAT_MODRM | INAT_VEXOK,
+       [0x55] = INAT_MODRM | INAT_VEXOK,
+       [0x56] = INAT_MODRM | INAT_VEXOK,
+       [0x57] = INAT_MODRM | INAT_VEXOK,
+       [0x58] = INAT_MODRM | INAT_VEXOK,
+       [0x59] = INAT_MODRM | INAT_VEXOK,
+       [0x5a] = INAT_MODRM | INAT_VEXOK,
+       [0x5b] = INAT_MODRM | INAT_VEXOK,
+       [0x5c] = INAT_MODRM | INAT_VEXOK,
+       [0x5d] = INAT_MODRM | INAT_VEXOK,
+       [0x5e] = INAT_MODRM | INAT_VEXOK,
+       [0x5f] = INAT_MODRM | INAT_VEXOK,
+       [0x60] = INAT_MODRM | INAT_VEXOK,
+       [0x61] = INAT_MODRM | INAT_VEXOK,
+       [0x62] = INAT_MODRM | INAT_VEXOK,
+       [0x63] = INAT_MODRM | INAT_VEXOK,
+       [0x64] = INAT_MODRM | INAT_VEXOK,
+       [0x65] = INAT_MODRM | INAT_VEXOK,
+       [0x66] = INAT_MODRM | INAT_VEXOK,
+       [0x67] = INAT_MODRM | INAT_VEXOK,
+       [0x68] = INAT_MODRM | INAT_VEXOK,
+       [0x69] = INAT_MODRM | INAT_VEXOK,
+       [0x6a] = INAT_MODRM | INAT_VEXOK,
+       [0x6b] = INAT_MODRM | INAT_VEXOK,
+       [0x6c] = INAT_MODRM | INAT_VEXOK,
+       [0x6d] = INAT_MODRM | INAT_VEXOK,
+       [0x6e] = INAT_MODRM | INAT_VEXOK,
+       [0x6f] = INAT_MODRM | INAT_VEXOK,
+       [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x74] = INAT_MODRM | INAT_VEXOK,
+       [0x75] = INAT_MODRM | INAT_VEXOK,
+       [0x76] = INAT_MODRM | INAT_VEXOK,
+       [0x7c] = INAT_MODRM | INAT_VEXOK,
+       [0x7d] = INAT_MODRM | INAT_VEXOK,
+       [0x7e] = INAT_MODRM | INAT_VEXOK,
+       [0x7f] = INAT_MODRM | INAT_VEXOK,
+       [0xbc] = INAT_MODRM,
+       [0xbd] = INAT_MODRM,
+       [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0xc4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0xc5] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0xc6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0xd0] = INAT_MODRM | INAT_VEXOK,
+       [0xd1] = INAT_MODRM | INAT_VEXOK,
+       [0xd2] = INAT_MODRM | INAT_VEXOK,
+       [0xd3] = INAT_MODRM | INAT_VEXOK,
+       [0xd4] = INAT_MODRM | INAT_VEXOK,
+       [0xd5] = INAT_MODRM | INAT_VEXOK,
+       [0xd6] = INAT_MODRM | INAT_VEXOK,
+       [0xd7] = INAT_MODRM | INAT_VEXOK,
+       [0xd8] = INAT_MODRM | INAT_VEXOK,
+       [0xd9] = INAT_MODRM | INAT_VEXOK,
+       [0xda] = INAT_MODRM | INAT_VEXOK,
+       [0xdb] = INAT_MODRM | INAT_VEXOK,
+       [0xdc] = INAT_MODRM | INAT_VEXOK,
+       [0xdd] = INAT_MODRM | INAT_VEXOK,
+       [0xde] = INAT_MODRM | INAT_VEXOK,
+       [0xdf] = INAT_MODRM | INAT_VEXOK,
+       [0xe0] = INAT_MODRM | INAT_VEXOK,
+       [0xe1] = INAT_MODRM | INAT_VEXOK,
+       [0xe2] = INAT_MODRM | INAT_VEXOK,
+       [0xe3] = INAT_MODRM | INAT_VEXOK,
+       [0xe4] = INAT_MODRM | INAT_VEXOK,
+       [0xe5] = INAT_MODRM | INAT_VEXOK,
+       [0xe6] = INAT_MODRM | INAT_VEXOK,
+       [0xe7] = INAT_MODRM | INAT_VEXOK,
+       [0xe8] = INAT_MODRM | INAT_VEXOK,
+       [0xe9] = INAT_MODRM | INAT_VEXOK,
+       [0xea] = INAT_MODRM | INAT_VEXOK,
+       [0xeb] = INAT_MODRM | INAT_VEXOK,
+       [0xec] = INAT_MODRM | INAT_VEXOK,
+       [0xed] = INAT_MODRM | INAT_VEXOK,
+       [0xee] = INAT_MODRM | INAT_VEXOK,
+       [0xef] = INAT_MODRM | INAT_VEXOK,
+       [0xf1] = INAT_MODRM | INAT_VEXOK,
+       [0xf2] = INAT_MODRM | INAT_VEXOK,
+       [0xf3] = INAT_MODRM | INAT_VEXOK,
+       [0xf4] = INAT_MODRM | INAT_VEXOK,
+       [0xf5] = INAT_MODRM | INAT_VEXOK,
+       [0xf6] = INAT_MODRM | INAT_VEXOK,
+       [0xf7] = INAT_MODRM | INAT_VEXOK,
+       [0xf8] = INAT_MODRM | INAT_VEXOK,
+       [0xf9] = INAT_MODRM | INAT_VEXOK,
+       [0xfa] = INAT_MODRM | INAT_VEXOK,
+       [0xfb] = INAT_MODRM | INAT_VEXOK,
+       [0xfc] = INAT_MODRM | INAT_VEXOK,
+       [0xfd] = INAT_MODRM | INAT_VEXOK,
+       [0xfe] = INAT_MODRM | INAT_VEXOK,
+};
+const insn_attr_t inat_escape_table_1_2[INAT_OPCODE_TABLE_SIZE] = {
+       [0x10] = INAT_MODRM | INAT_VEXOK,
+       [0x11] = INAT_MODRM | INAT_VEXOK,
+       [0x12] = INAT_MODRM | INAT_VEXOK,
+       [0x16] = INAT_MODRM | INAT_VEXOK,
+       [0x2a] = INAT_MODRM | INAT_VEXOK,
+       [0x2c] = INAT_MODRM | INAT_VEXOK,
+       [0x2d] = INAT_MODRM | INAT_VEXOK,
+       [0x51] = INAT_MODRM | INAT_VEXOK,
+       [0x52] = INAT_MODRM | INAT_VEXOK,
+       [0x53] = INAT_MODRM | INAT_VEXOK,
+       [0x58] = INAT_MODRM | INAT_VEXOK,
+       [0x59] = INAT_MODRM | INAT_VEXOK,
+       [0x5a] = INAT_MODRM | INAT_VEXOK,
+       [0x5b] = INAT_MODRM | INAT_VEXOK,
+       [0x5c] = INAT_MODRM | INAT_VEXOK,
+       [0x5d] = INAT_MODRM | INAT_VEXOK,
+       [0x5e] = INAT_MODRM | INAT_VEXOK,
+       [0x5f] = INAT_MODRM | INAT_VEXOK,
+       [0x6f] = INAT_MODRM | INAT_VEXOK,
+       [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x7e] = INAT_MODRM | INAT_VEXOK,
+       [0x7f] = INAT_MODRM | INAT_VEXOK,
+       [0xb8] = INAT_MODRM,
+       [0xbc] = INAT_MODRM,
+       [0xbd] = INAT_MODRM,
+       [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0xd6] = INAT_MODRM,
+       [0xe6] = INAT_MODRM | INAT_VEXOK,
+};
+const insn_attr_t inat_escape_table_1_3[INAT_OPCODE_TABLE_SIZE] = {
+       [0x10] = INAT_MODRM | INAT_VEXOK,
+       [0x11] = INAT_MODRM | INAT_VEXOK,
+       [0x12] = INAT_MODRM | INAT_VEXOK,
+       [0x2a] = INAT_MODRM | INAT_VEXOK,
+       [0x2c] = INAT_MODRM | INAT_VEXOK,
+       [0x2d] = INAT_MODRM | INAT_VEXOK,
+       [0x51] = INAT_MODRM | INAT_VEXOK,
+       [0x58] = INAT_MODRM | INAT_VEXOK,
+       [0x59] = INAT_MODRM | INAT_VEXOK,
+       [0x5a] = INAT_MODRM | INAT_VEXOK,
+       [0x5c] = INAT_MODRM | INAT_VEXOK,
+       [0x5d] = INAT_MODRM | INAT_VEXOK,
+       [0x5e] = INAT_MODRM | INAT_VEXOK,
+       [0x5f] = INAT_MODRM | INAT_VEXOK,
+       [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x7c] = INAT_MODRM | INAT_VEXOK,
+       [0x7d] = INAT_MODRM | INAT_VEXOK,
+       [0xbc] = INAT_MODRM,
+       [0xbd] = INAT_MODRM,
+       [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0xd0] = INAT_MODRM | INAT_VEXOK,
+       [0xd6] = INAT_MODRM,
+       [0xe6] = INAT_MODRM | INAT_VEXOK,
+       [0xf0] = INAT_MODRM | INAT_VEXOK,
+};
+
+/* Table: 3-byte opcode 1 (0x0f 0x38) */
+const insn_attr_t inat_escape_table_2[INAT_OPCODE_TABLE_SIZE] = {
+       [0x00] = INAT_MODRM | INAT_VARIANT,
+       [0x01] = INAT_MODRM | INAT_VARIANT,
+       [0x02] = INAT_MODRM | INAT_VARIANT,
+       [0x03] = INAT_MODRM | INAT_VARIANT,
+       [0x04] = INAT_MODRM | INAT_VARIANT,
+       [0x05] = INAT_MODRM | INAT_VARIANT,
+       [0x06] = INAT_MODRM | INAT_VARIANT,
+       [0x07] = INAT_MODRM | INAT_VARIANT,
+       [0x08] = INAT_MODRM | INAT_VARIANT,
+       [0x09] = INAT_MODRM | INAT_VARIANT,
+       [0x0a] = INAT_MODRM | INAT_VARIANT,
+       [0x0b] = INAT_MODRM | INAT_VARIANT,
+       [0x0c] = INAT_VARIANT,
+       [0x0d] = INAT_VARIANT,
+       [0x0e] = INAT_VARIANT,
+       [0x0f] = INAT_VARIANT,
+       [0x10] = INAT_VARIANT,
+       [0x13] = INAT_VARIANT,
+       [0x14] = INAT_VARIANT,
+       [0x15] = INAT_VARIANT,
+       [0x16] = INAT_VARIANT,
+       [0x17] = INAT_VARIANT,
+       [0x18] = INAT_VARIANT,
+       [0x19] = INAT_VARIANT,
+       [0x1a] = INAT_VARIANT,
+       [0x1c] = INAT_MODRM | INAT_VARIANT,
+       [0x1d] = INAT_MODRM | INAT_VARIANT,
+       [0x1e] = INAT_MODRM | INAT_VARIANT,
+       [0x20] = INAT_VARIANT,
+       [0x21] = INAT_VARIANT,
+       [0x22] = INAT_VARIANT,
+       [0x23] = INAT_VARIANT,
+       [0x24] = INAT_VARIANT,
+       [0x25] = INAT_VARIANT,
+       [0x28] = INAT_VARIANT,
+       [0x29] = INAT_VARIANT,
+       [0x2a] = INAT_VARIANT,
+       [0x2b] = INAT_VARIANT,
+       [0x2c] = INAT_VARIANT,
+       [0x2d] = INAT_VARIANT,
+       [0x2e] = INAT_VARIANT,
+       [0x2f] = INAT_VARIANT,
+       [0x30] = INAT_VARIANT,
+       [0x31] = INAT_VARIANT,
+       [0x32] = INAT_VARIANT,
+       [0x33] = INAT_VARIANT,
+       [0x34] = INAT_VARIANT,
+       [0x35] = INAT_VARIANT,
+       [0x36] = INAT_VARIANT,
+       [0x37] = INAT_VARIANT,
+       [0x38] = INAT_VARIANT,
+       [0x39] = INAT_VARIANT,
+       [0x3a] = INAT_VARIANT,
+       [0x3b] = INAT_VARIANT,
+       [0x3c] = INAT_VARIANT,
+       [0x3d] = INAT_VARIANT,
+       [0x3e] = INAT_VARIANT,
+       [0x3f] = INAT_VARIANT,
+       [0x40] = INAT_VARIANT,
+       [0x41] = INAT_VARIANT,
+       [0x45] = INAT_VARIANT,
+       [0x46] = INAT_VARIANT,
+       [0x47] = INAT_VARIANT,
+       [0x58] = INAT_VARIANT,
+       [0x59] = INAT_VARIANT,
+       [0x5a] = INAT_VARIANT,
+       [0x78] = INAT_VARIANT,
+       [0x79] = INAT_VARIANT,
+       [0x80] = INAT_VARIANT,
+       [0x81] = INAT_VARIANT,
+       [0x82] = INAT_VARIANT,
+       [0x8c] = INAT_VARIANT,
+       [0x8e] = INAT_VARIANT,
+       [0x90] = INAT_VARIANT,
+       [0x91] = INAT_VARIANT,
+       [0x92] = INAT_VARIANT,
+       [0x93] = INAT_VARIANT,
+       [0x96] = INAT_VARIANT,
+       [0x97] = INAT_VARIANT,
+       [0x98] = INAT_VARIANT,
+       [0x99] = INAT_VARIANT,
+       [0x9a] = INAT_VARIANT,
+       [0x9b] = INAT_VARIANT,
+       [0x9c] = INAT_VARIANT,
+       [0x9d] = INAT_VARIANT,
+       [0x9e] = INAT_VARIANT,
+       [0x9f] = INAT_VARIANT,
+       [0xa6] = INAT_VARIANT,
+       [0xa7] = INAT_VARIANT,
+       [0xa8] = INAT_VARIANT,
+       [0xa9] = INAT_VARIANT,
+       [0xaa] = INAT_VARIANT,
+       [0xab] = INAT_VARIANT,
+       [0xac] = INAT_VARIANT,
+       [0xad] = INAT_VARIANT,
+       [0xae] = INAT_VARIANT,
+       [0xaf] = INAT_VARIANT,
+       [0xb6] = INAT_VARIANT,
+       [0xb7] = INAT_VARIANT,
+       [0xb8] = INAT_VARIANT,
+       [0xb9] = INAT_VARIANT,
+       [0xba] = INAT_VARIANT,
+       [0xbb] = INAT_VARIANT,
+       [0xbc] = INAT_VARIANT,
+       [0xbd] = INAT_VARIANT,
+       [0xbe] = INAT_VARIANT,
+       [0xbf] = INAT_VARIANT,
+       [0xdb] = INAT_VARIANT,
+       [0xdc] = INAT_VARIANT,
+       [0xdd] = INAT_VARIANT,
+       [0xde] = INAT_VARIANT,
+       [0xdf] = INAT_VARIANT,
+       [0xf0] = INAT_MODRM | INAT_VARIANT,
+       [0xf1] = INAT_MODRM | INAT_VARIANT,
+       [0xf2] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xf3] = INAT_MAKE_GROUP(22),
+       [0xf5] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY | INAT_VARIANT,
+       [0xf6] = INAT_VARIANT,
+       [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY | INAT_VARIANT,
+};
+const insn_attr_t inat_escape_table_2_1[INAT_OPCODE_TABLE_SIZE] = {
+       [0x00] = INAT_MODRM | INAT_VEXOK,
+       [0x01] = INAT_MODRM | INAT_VEXOK,
+       [0x02] = INAT_MODRM | INAT_VEXOK,
+       [0x03] = INAT_MODRM | INAT_VEXOK,
+       [0x04] = INAT_MODRM | INAT_VEXOK,
+       [0x05] = INAT_MODRM | INAT_VEXOK,
+       [0x06] = INAT_MODRM | INAT_VEXOK,
+       [0x07] = INAT_MODRM | INAT_VEXOK,
+       [0x08] = INAT_MODRM | INAT_VEXOK,
+       [0x09] = INAT_MODRM | INAT_VEXOK,
+       [0x0a] = INAT_MODRM | INAT_VEXOK,
+       [0x0b] = INAT_MODRM | INAT_VEXOK,
+       [0x0c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x0d] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x0e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x0f] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x10] = INAT_MODRM,
+       [0x13] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x14] = INAT_MODRM,
+       [0x15] = INAT_MODRM,
+       [0x16] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x17] = INAT_MODRM | INAT_VEXOK,
+       [0x18] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x19] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x1a] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x1c] = INAT_MODRM | INAT_VEXOK,
+       [0x1d] = INAT_MODRM | INAT_VEXOK,
+       [0x1e] = INAT_MODRM | INAT_VEXOK,
+       [0x20] = INAT_MODRM | INAT_VEXOK,
+       [0x21] = INAT_MODRM | INAT_VEXOK,
+       [0x22] = INAT_MODRM | INAT_VEXOK,
+       [0x23] = INAT_MODRM | INAT_VEXOK,
+       [0x24] = INAT_MODRM | INAT_VEXOK,
+       [0x25] = INAT_MODRM | INAT_VEXOK,
+       [0x28] = INAT_MODRM | INAT_VEXOK,
+       [0x29] = INAT_MODRM | INAT_VEXOK,
+       [0x2a] = INAT_MODRM | INAT_VEXOK,
+       [0x2b] = INAT_MODRM | INAT_VEXOK,
+       [0x2c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x2d] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x2e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x2f] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x30] = INAT_MODRM | INAT_VEXOK,
+       [0x31] = INAT_MODRM | INAT_VEXOK,
+       [0x32] = INAT_MODRM | INAT_VEXOK,
+       [0x33] = INAT_MODRM | INAT_VEXOK,
+       [0x34] = INAT_MODRM | INAT_VEXOK,
+       [0x35] = INAT_MODRM | INAT_VEXOK,
+       [0x36] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x37] = INAT_MODRM | INAT_VEXOK,
+       [0x38] = INAT_MODRM | INAT_VEXOK,
+       [0x39] = INAT_MODRM | INAT_VEXOK,
+       [0x3a] = INAT_MODRM | INAT_VEXOK,
+       [0x3b] = INAT_MODRM | INAT_VEXOK,
+       [0x3c] = INAT_MODRM | INAT_VEXOK,
+       [0x3d] = INAT_MODRM | INAT_VEXOK,
+       [0x3e] = INAT_MODRM | INAT_VEXOK,
+       [0x3f] = INAT_MODRM | INAT_VEXOK,
+       [0x40] = INAT_MODRM | INAT_VEXOK,
+       [0x41] = INAT_MODRM | INAT_VEXOK,
+       [0x45] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x46] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x47] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x58] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x59] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x5a] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x78] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x79] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x80] = INAT_MODRM,
+       [0x81] = INAT_MODRM,
+       [0x82] = INAT_MODRM,
+       [0x8c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x8e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x90] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x91] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x92] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x93] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x96] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x97] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x98] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x99] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x9a] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x9b] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x9c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x9d] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x9e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x9f] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xa6] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xa7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xa8] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xa9] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xaa] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xab] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xac] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xad] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xae] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xaf] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xb6] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xb7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xb8] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xb9] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xba] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xbb] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xbc] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xbd] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xbe] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xbf] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xdb] = INAT_MODRM | INAT_VEXOK,
+       [0xdc] = INAT_MODRM | INAT_VEXOK,
+       [0xdd] = INAT_MODRM | INAT_VEXOK,
+       [0xde] = INAT_MODRM | INAT_VEXOK,
+       [0xdf] = INAT_MODRM | INAT_VEXOK,
+       [0xf0] = INAT_MODRM,
+       [0xf1] = INAT_MODRM,
+       [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+};
+const insn_attr_t inat_escape_table_2_2[INAT_OPCODE_TABLE_SIZE] = {
+       [0xf5] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+};
+const insn_attr_t inat_escape_table_2_3[INAT_OPCODE_TABLE_SIZE] = {
+       [0xf0] = INAT_MODRM,
+       [0xf1] = INAT_MODRM,
+       [0xf5] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xf6] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+};
+
+/* Table: 3-byte opcode 2 (0x0f 0x3a) */
+const insn_attr_t inat_escape_table_3[INAT_OPCODE_TABLE_SIZE] = {
+       [0x00] = INAT_VARIANT,
+       [0x01] = INAT_VARIANT,
+       [0x02] = INAT_VARIANT,
+       [0x04] = INAT_VARIANT,
+       [0x05] = INAT_VARIANT,
+       [0x06] = INAT_VARIANT,
+       [0x08] = INAT_VARIANT,
+       [0x09] = INAT_VARIANT,
+       [0x0a] = INAT_VARIANT,
+       [0x0b] = INAT_VARIANT,
+       [0x0c] = INAT_VARIANT,
+       [0x0d] = INAT_VARIANT,
+       [0x0e] = INAT_VARIANT,
+       [0x0f] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0x14] = INAT_VARIANT,
+       [0x15] = INAT_VARIANT,
+       [0x16] = INAT_VARIANT,
+       [0x17] = INAT_VARIANT,
+       [0x18] = INAT_VARIANT,
+       [0x19] = INAT_VARIANT,
+       [0x1d] = INAT_VARIANT,
+       [0x20] = INAT_VARIANT,
+       [0x21] = INAT_VARIANT,
+       [0x22] = INAT_VARIANT,
+       [0x38] = INAT_VARIANT,
+       [0x39] = INAT_VARIANT,
+       [0x40] = INAT_VARIANT,
+       [0x41] = INAT_VARIANT,
+       [0x42] = INAT_VARIANT,
+       [0x44] = INAT_VARIANT,
+       [0x46] = INAT_VARIANT,
+       [0x4a] = INAT_VARIANT,
+       [0x4b] = INAT_VARIANT,
+       [0x4c] = INAT_VARIANT,
+       [0x60] = INAT_VARIANT,
+       [0x61] = INAT_VARIANT,
+       [0x62] = INAT_VARIANT,
+       [0x63] = INAT_VARIANT,
+       [0xdf] = INAT_VARIANT,
+       [0xf0] = INAT_VARIANT,
+};
+const insn_attr_t inat_escape_table_3_1[INAT_OPCODE_TABLE_SIZE] = {
+       [0x00] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x01] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x02] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x04] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x05] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x06] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x08] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x09] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x0a] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x0b] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x0c] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x0d] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x0e] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x0f] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x14] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x15] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x16] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x17] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x18] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x19] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x1d] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x20] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x21] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x22] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x38] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x39] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x40] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x41] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x42] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x44] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x46] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x4a] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x4b] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+       [0x4c] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x60] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x61] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x62] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x63] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0xdf] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+};
+const insn_attr_t inat_escape_table_3_3[INAT_OPCODE_TABLE_SIZE] = {
+       [0xf0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | 
INAT_VEXONLY,
+};
+
+/* GrpTable: Grp1 */
+
+/* GrpTable: Grp1A */
+
+/* GrpTable: Grp2 */
+
+/* GrpTable: Grp3_1 */
+const insn_attr_t inat_group_table_5[INAT_GROUP_TABLE_SIZE] = {
+       [0x0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM,
+       [0x2] = INAT_MODRM,
+       [0x3] = INAT_MODRM,
+       [0x4] = INAT_MODRM,
+       [0x5] = INAT_MODRM,
+       [0x6] = INAT_MODRM,
+       [0x7] = INAT_MODRM,
+};
+
+/* GrpTable: Grp3_2 */
+const insn_attr_t inat_group_table_6[INAT_GROUP_TABLE_SIZE] = {
+       [0x0] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM,
+       [0x2] = INAT_MODRM,
+       [0x3] = INAT_MODRM,
+       [0x4] = INAT_MODRM,
+       [0x5] = INAT_MODRM,
+       [0x6] = INAT_MODRM,
+       [0x7] = INAT_MODRM,
+};
+
+/* GrpTable: Grp4 */
+const insn_attr_t inat_group_table_7[INAT_GROUP_TABLE_SIZE] = {
+       [0x0] = INAT_MODRM,
+       [0x1] = INAT_MODRM,
+};
+
+/* GrpTable: Grp5 */
+const insn_attr_t inat_group_table_8[INAT_GROUP_TABLE_SIZE] = {
+       [0x0] = INAT_MODRM,
+       [0x1] = INAT_MODRM,
+       [0x2] = INAT_MODRM | INAT_FORCE64,
+       [0x3] = INAT_MODRM,
+       [0x4] = INAT_MODRM | INAT_FORCE64,
+       [0x5] = INAT_MODRM,
+       [0x6] = INAT_MODRM | INAT_FORCE64,
+};
+
+/* GrpTable: Grp6 */
+const insn_attr_t inat_group_table_9[INAT_GROUP_TABLE_SIZE] = {
+       [0x0] = INAT_MODRM,
+       [0x1] = INAT_MODRM,
+       [0x2] = INAT_MODRM,
+       [0x3] = INAT_MODRM,
+       [0x4] = INAT_MODRM,
+       [0x5] = INAT_MODRM,
+};
+
+/* GrpTable: Grp7 */
+const insn_attr_t inat_group_table_10[INAT_GROUP_TABLE_SIZE] = {
+       [0x0] = INAT_MODRM,
+       [0x1] = INAT_MODRM,
+       [0x2] = INAT_MODRM,
+       [0x3] = INAT_MODRM,
+       [0x4] = INAT_MODRM,
+       [0x6] = INAT_MODRM,
+       [0x7] = INAT_MODRM,
+};
+
+/* GrpTable: Grp8 */
+
+/* GrpTable: Grp9 */
+const insn_attr_t inat_group_table_21[INAT_GROUP_TABLE_SIZE] = {
+       [0x1] = INAT_MODRM,
+       [0x6] = INAT_MODRM | INAT_MODRM | INAT_VARIANT,
+       [0x7] = INAT_MODRM | INAT_VARIANT,
+};
+const insn_attr_t inat_group_table_21_1[INAT_GROUP_TABLE_SIZE] = {
+       [0x6] = INAT_MODRM,
+};
+const insn_attr_t inat_group_table_21_2[INAT_GROUP_TABLE_SIZE] = {
+       [0x6] = INAT_MODRM,
+       [0x7] = INAT_MODRM,
+};
+
+/* GrpTable: Grp10 */
+
+/* GrpTable: Grp11 */
+
+/* GrpTable: Grp12 */
+const insn_attr_t inat_group_table_13[INAT_GROUP_TABLE_SIZE] = {
+       [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+};
+const insn_attr_t inat_group_table_13_1[INAT_GROUP_TABLE_SIZE] = {
+       [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+};
+
+/* GrpTable: Grp13 */
+const insn_attr_t inat_group_table_14[INAT_GROUP_TABLE_SIZE] = {
+       [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+};
+const insn_attr_t inat_group_table_14_1[INAT_GROUP_TABLE_SIZE] = {
+       [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+};
+
+/* GrpTable: Grp14 */
+const insn_attr_t inat_group_table_15[INAT_GROUP_TABLE_SIZE] = {
+       [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0x3] = INAT_VARIANT,
+       [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT,
+       [0x7] = INAT_VARIANT,
+};
+const insn_attr_t inat_group_table_15_1[INAT_GROUP_TABLE_SIZE] = {
+       [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x3] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+       [0x7] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK,
+};
+
+/* GrpTable: Grp15 */
+const insn_attr_t inat_group_table_18[INAT_GROUP_TABLE_SIZE] = {
+       [0x0] = INAT_VARIANT,
+       [0x1] = INAT_VARIANT,
+       [0x2] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+       [0x3] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT,
+};
+const insn_attr_t inat_group_table_18_2[INAT_GROUP_TABLE_SIZE] = {
+       [0x0] = INAT_MODRM,
+       [0x1] = INAT_MODRM,
+       [0x2] = INAT_MODRM,
+       [0x3] = INAT_MODRM,
+};
+
+/* GrpTable: Grp16 */
+const insn_attr_t inat_group_table_12[INAT_GROUP_TABLE_SIZE] = {
+       [0x0] = INAT_MODRM,
+       [0x1] = INAT_MODRM,
+       [0x2] = INAT_MODRM,
+       [0x3] = INAT_MODRM,
+};
+
+/* GrpTable: Grp17 */
+const insn_attr_t inat_group_table_22[INAT_GROUP_TABLE_SIZE] = {
+       [0x1] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x2] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+       [0x3] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY,
+};
+
+/* GrpTable: GrpP */
+
+/* GrpTable: GrpPDLK */
+
+/* GrpTable: GrpRNG */
+
+/* Escape opcode map array */
+const insn_attr_t * const inat_escape_tables[INAT_ESC_MAX + 1][INAT_LSTPFX_MAX 
+ 1] = {
+       [1][0] = inat_escape_table_1,
+       [1][1] = inat_escape_table_1_1,
+       [1][2] = inat_escape_table_1_2,
+       [1][3] = inat_escape_table_1_3,
+       [2][0] = inat_escape_table_2,
+       [2][1] = inat_escape_table_2_1,
+       [2][2] = inat_escape_table_2_2,
+       [2][3] = inat_escape_table_2_3,
+       [3][0] = inat_escape_table_3,
+       [3][1] = inat_escape_table_3_1,
+       [3][3] = inat_escape_table_3_3,
+};
+
+/* Group opcode map array */
+const insn_attr_t * const inat_group_tables[INAT_GRP_MAX + 1][INAT_LSTPFX_MAX 
+ 1] = {
+       [5][0] = inat_group_table_5,
+       [6][0] = inat_group_table_6,
+       [7][0] = inat_group_table_7,
+       [8][0] = inat_group_table_8,
+       [9][0] = inat_group_table_9,
+       [10][0] = inat_group_table_10,
+       [12][0] = inat_group_table_12,
+       [13][0] = inat_group_table_13,
+       [13][1] = inat_group_table_13_1,
+       [14][0] = inat_group_table_14,
+       [14][1] = inat_group_table_14_1,
+       [15][0] = inat_group_table_15,
+       [15][1] = inat_group_table_15_1,
+       [18][0] = inat_group_table_18,
+       [18][2] = inat_group_table_18_2,
+       [21][0] = inat_group_table_21,
+       [21][1] = inat_group_table_21_1,
+       [21][2] = inat_group_table_21_2,
+       [22][0] = inat_group_table_22,
+};
+
+/* AVX opcode map array */
+const insn_attr_t * const inat_avx_tables[X86_VEX_M_MAX + 1][INAT_LSTPFX_MAX + 
1] = {
+       [1][0] = inat_escape_table_1,
+       [1][1] = inat_escape_table_1_1,
+       [1][2] = inat_escape_table_1_2,
+       [1][3] = inat_escape_table_1_3,
+       [2][0] = inat_escape_table_2,
+       [2][1] = inat_escape_table_2_1,
+       [2][2] = inat_escape_table_2_2,
+       [2][3] = inat_escape_table_2_3,
+       [3][0] = inat_escape_table_3,
+       [3][1] = inat_escape_table_3_1,
+       [3][3] = inat_escape_table_3_3,
+};
diff --git a/xen/arch/x86/inat.c b/xen/arch/x86/inat.c
new file mode 100644
index 0000000..feeaa50
--- /dev/null
+++ b/xen/arch/x86/inat.c
@@ -0,0 +1,96 @@
+/*
+ * x86 instruction attribute tables
+ *
+ * Written by Masami Hiramatsu <mhiramat@xxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+#include <asm/insn.h>
+
+/* Attribute tables are generated from opcode map */
+#include "inat-tables.c"
+
+/* Attribute search APIs */
+insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode)
+{
+       return inat_primary_table[opcode];
+}
+
+int inat_get_last_prefix_id(insn_byte_t last_pfx)
+{
+       insn_attr_t lpfx_attr;
+
+       lpfx_attr = inat_get_opcode_attribute(last_pfx);
+       return inat_last_prefix_id(lpfx_attr);
+}
+
+insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id,
+                                     insn_attr_t esc_attr)
+{
+       const insn_attr_t *table;
+       int n;
+
+       n = inat_escape_id(esc_attr);
+
+       table = inat_escape_tables[n][0];
+       if (!table)
+               return 0;
+       if (inat_has_variant(table[opcode]) && lpfx_id) {
+               table = inat_escape_tables[n][lpfx_id];
+               if (!table)
+                       return 0;
+       }
+       return table[opcode];
+}
+
+insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id,
+                                    insn_attr_t grp_attr)
+{
+       const insn_attr_t *table;
+       int n;
+
+       n = inat_group_id(grp_attr);
+
+       table = inat_group_tables[n][0];
+       if (!table)
+               return inat_group_common_attribute(grp_attr);
+       if (inat_has_variant(table[X86_MODRM_REG(modrm)]) && lpfx_id) {
+               table = inat_group_tables[n][lpfx_id];
+               if (!table)
+                       return inat_group_common_attribute(grp_attr);
+       }
+       return table[X86_MODRM_REG(modrm)] |
+              inat_group_common_attribute(grp_attr);
+}
+
+insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
+                                  insn_byte_t vex_p)
+{
+       const insn_attr_t *table;
+       if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX)
+               return 0;
+       /* At first, this checks the master table */
+       table = inat_avx_tables[vex_m][0];
+       if (!table)
+               return 0;
+       if (!inat_is_group(table[opcode]) && vex_p) {
+               /* If this is not a group, get attribute directly */
+               table = inat_avx_tables[vex_m][vex_p];
+               if (!table)
+                       return 0;
+       }
+       return table[opcode];
+}
diff --git a/xen/arch/x86/insn.c b/xen/arch/x86/insn.c
new file mode 100644
index 0000000..5aea2c7
--- /dev/null
+++ b/xen/arch/x86/insn.c
@@ -0,0 +1,576 @@
+/*
+ * x86 instruction analysis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004, 2009
+ */
+
+#include <xen/string.h>
+#include <asm/inat.h>
+#include <asm/insn.h>
+
+/* Verify next sizeof(t) bytes can be on the same instruction */
+#define validate_next(t, insn, n)      \
+       ((insn)->next_byte + sizeof(t) + n - (insn)->kaddr <= MAX_INSN_SIZE)
+
+#define __get_next(t, insn)    \
+       ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+
+#define __peek_nbyte_next(t, insn, n)  \
+       ({ t r = *(t*)((insn)->next_byte + n); r; })
+
+#define get_next(t, insn)      \
+       ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; 
__get_next(t, insn); })
+
+#define peek_nbyte_next(t, insn, n)    \
+       ({ if (unlikely(!validate_next(t, insn, n))) goto err_out; 
__peek_nbyte_next(t, insn, n); })
+
+#define peek_next(t, insn)     peek_nbyte_next(t, insn, 0)
+
+/**
+ * insn_init() - initialize struct insn
+ * @insn:      &struct insn to be initialized
+ * @kaddr:     address (in kernel memory) of instruction (or copy thereof)
+ * @x86_64:    !0 for 64-bit kernel or 64-bit app
+ */
+void insn_init(struct insn *insn, const void *kaddr, int x86_64)
+{
+       memset(insn, 0, sizeof(*insn));
+       insn->kaddr = kaddr;
+       insn->next_byte = kaddr;
+       insn->x86_64 = x86_64 ? 1 : 0;
+       insn->opnd_bytes = 4;
+       if (x86_64)
+               insn->addr_bytes = 8;
+       else
+               insn->addr_bytes = 4;
+}
+
+/**
+ * insn_get_prefixes - scan x86 instruction prefix bytes
+ * @insn:      &struct insn containing instruction
+ *
+ * Populates the @insn->prefixes bitmap, and updates @insn->next_byte
+ * to point to the (first) opcode.  No effect if @insn->prefixes.got
+ * is already set.
+ */
+void insn_get_prefixes(struct insn *insn)
+{
+       struct insn_field *prefixes = &insn->prefixes;
+       insn_attr_t attr;
+       insn_byte_t b, lb;
+       int i, nb;
+
+       if (prefixes->got)
+               return;
+
+       nb = 0;
+       lb = 0;
+       b = peek_next(insn_byte_t, insn);
+       attr = inat_get_opcode_attribute(b);
+       while (inat_is_legacy_prefix(attr)) {
+               /* Skip if same prefix */
+               for (i = 0; i < nb; i++)
+                       if (prefixes->bytes[i] == b)
+                               goto found;
+               if (nb == 4)
+                       /* Invalid instruction */
+                       break;
+               prefixes->bytes[nb++] = b;
+               if (inat_is_address_size_prefix(attr)) {
+                       /* address size switches 2/4 or 4/8 */
+                       if (insn->x86_64)
+                               insn->addr_bytes ^= 12;
+                       else
+                               insn->addr_bytes ^= 6;
+               } else if (inat_is_operand_size_prefix(attr)) {
+                       /* oprand size switches 2/4 */
+                       insn->opnd_bytes ^= 6;
+               }
+found:
+               prefixes->nbytes++;
+               insn->next_byte++;
+               lb = b;
+               b = peek_next(insn_byte_t, insn);
+               attr = inat_get_opcode_attribute(b);
+       }
+       /* Set the last prefix */
+       if (lb && lb != insn->prefixes.bytes[3]) {
+               if (unlikely(insn->prefixes.bytes[3])) {
+                       /* Swap the last prefix */
+                       b = insn->prefixes.bytes[3];
+                       for (i = 0; i < nb; i++)
+                               if (prefixes->bytes[i] == lb)
+                                       prefixes->bytes[i] = b;
+               }
+               insn->prefixes.bytes[3] = lb;
+       }
+
+       /* Decode REX prefix */
+       if (insn->x86_64) {
+               b = peek_next(insn_byte_t, insn);
+               attr = inat_get_opcode_attribute(b);
+               if (inat_is_rex_prefix(attr)) {
+                       insn->rex_prefix.value = b;
+                       insn->rex_prefix.nbytes = 1;
+                       insn->next_byte++;
+                       if (X86_REX_W(b))
+                               /* REX.W overrides opnd_size */
+                               insn->opnd_bytes = 8;
+               }
+       }
+       insn->rex_prefix.got = 1;
+
+       /* Decode VEX prefix */
+       b = peek_next(insn_byte_t, insn);
+       attr = inat_get_opcode_attribute(b);
+       if (inat_is_vex_prefix(attr)) {
+               insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
+               if (!insn->x86_64) {
+                       /*
+                        * In 32-bits mode, if the [7:6] bits (mod bits of
+                        * ModRM) on the second byte are not 11b, it is
+                        * LDS or LES.
+                        */
+                       if (X86_MODRM_MOD(b2) != 3)
+                               goto vex_end;
+               }
+               insn->vex_prefix.bytes[0] = b;
+               insn->vex_prefix.bytes[1] = b2;
+               if (inat_is_vex3_prefix(attr)) {
+                       b2 = peek_nbyte_next(insn_byte_t, insn, 2);
+                       insn->vex_prefix.bytes[2] = b2;
+                       insn->vex_prefix.nbytes = 3;
+                       insn->next_byte += 3;
+                       if (insn->x86_64 && X86_VEX_W(b2))
+                               /* VEX.W overrides opnd_size */
+                               insn->opnd_bytes = 8;
+               } else {
+                       insn->vex_prefix.nbytes = 2;
+                       insn->next_byte += 2;
+               }
+       }
+vex_end:
+       insn->vex_prefix.got = 1;
+
+       prefixes->got = 1;
+
+err_out:
+       return;
+}
+
+/**
+ * insn_get_opcode - collect opcode(s)
+ * @insn:      &struct insn containing instruction
+ *
+ * Populates @insn->opcode, updates @insn->next_byte to point past the
+ * opcode byte(s), and set @insn->attr (except for groups).
+ * If necessary, first collects any preceding (prefix) bytes.
+ * Sets @insn->opcode.value = opcode1.  No effect if @insn->opcode.got
+ * is already 1.
+ */
+void insn_get_opcode(struct insn *insn)
+{
+       struct insn_field *opcode = &insn->opcode;
+       insn_byte_t op;
+       int pfx_id;
+       if (opcode->got)
+               return;
+       if (!insn->prefixes.got)
+               insn_get_prefixes(insn);
+
+       /* Get first opcode */
+       op = get_next(insn_byte_t, insn);
+       opcode->bytes[0] = op;
+       opcode->nbytes = 1;
+
+       /* Check if there is VEX prefix or not */
+       if (insn_is_avx(insn)) {
+               insn_byte_t m, p;
+               m = insn_vex_m_bits(insn);
+               p = insn_vex_p_bits(insn);
+               insn->attr = inat_get_avx_attribute(op, m, p);
+               if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr))
+                       insn->attr = 0; /* This instruction is bad */
+               goto end;       /* VEX has only 1 byte for opcode */
+       }
+
+       insn->attr = inat_get_opcode_attribute(op);
+       while (inat_is_escape(insn->attr)) {
+               /* Get escaped opcode */
+               op = get_next(insn_byte_t, insn);
+               opcode->bytes[opcode->nbytes++] = op;
+               pfx_id = insn_last_prefix_id(insn);
+               insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr);
+       }
+       if (inat_must_vex(insn->attr))
+               insn->attr = 0; /* This instruction is bad */
+end:
+       opcode->got = 1;
+
+err_out:
+       return;
+}
+
+/**
+ * insn_get_modrm - collect ModRM byte, if any
+ * @insn:      &struct insn containing instruction
+ *
+ * Populates @insn->modrm and updates @insn->next_byte to point past the
+ * ModRM byte, if any.  If necessary, first collects the preceding bytes
+ * (prefixes and opcode(s)).  No effect if @insn->modrm.got is already 1.
+ */
+void insn_get_modrm(struct insn *insn)
+{
+       struct insn_field *modrm = &insn->modrm;
+       insn_byte_t pfx_id, mod;
+       if (modrm->got)
+               return;
+       if (!insn->opcode.got)
+               insn_get_opcode(insn);
+
+       if (inat_has_modrm(insn->attr)) {
+               mod = get_next(insn_byte_t, insn);
+               modrm->value = mod;
+               modrm->nbytes = 1;
+               if (inat_is_group(insn->attr)) {
+                       pfx_id = insn_last_prefix_id(insn);
+                       insn->attr = inat_get_group_attribute(mod, pfx_id,
+                                                             insn->attr);
+                       if (insn_is_avx(insn) && !inat_accept_vex(insn->attr))
+                               insn->attr = 0; /* This is bad */
+               }
+       }
+
+       if (insn->x86_64 && inat_is_force64(insn->attr))
+               insn->opnd_bytes = 8;
+       modrm->got = 1;
+
+err_out:
+       return;
+}
+
+
+/**
+ * insn_rip_relative() - Does instruction use RIP-relative addressing mode?
+ * @insn:      &struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * ModRM byte.  No effect if @insn->x86_64 is 0.
+ */
+int insn_rip_relative(struct insn *insn)
+{
+       struct insn_field *modrm = &insn->modrm;
+
+       if (!insn->x86_64)
+               return 0;
+       if (!modrm->got)
+               insn_get_modrm(insn);
+       /*
+        * For rip-relative instructions, the mod field (top 2 bits)
+        * is zero and the r/m field (bottom 3 bits) is 0x5.
+        */
+       return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
+}
+
+/**
+ * insn_get_sib() - Get the SIB byte of instruction
+ * @insn:      &struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * ModRM byte.
+ */
+void insn_get_sib(struct insn *insn)
+{
+       insn_byte_t modrm;
+
+       if (insn->sib.got)
+               return;
+       if (!insn->modrm.got)
+               insn_get_modrm(insn);
+       if (insn->modrm.nbytes) {
+               modrm = (insn_byte_t)insn->modrm.value;
+               if (insn->addr_bytes != 2 &&
+                   X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
+                       insn->sib.value = get_next(insn_byte_t, insn);
+                       insn->sib.nbytes = 1;
+               }
+       }
+       insn->sib.got = 1;
+
+err_out:
+       return;
+}
+
+
+/**
+ * insn_get_displacement() - Get the displacement of instruction
+ * @insn:      &struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * SIB byte.
+ * Displacement value is sign-expanded.
+ */
+void insn_get_displacement(struct insn *insn)
+{
+       insn_byte_t mod, rm, base;
+
+       if (insn->displacement.got)
+               return;
+       if (!insn->sib.got)
+               insn_get_sib(insn);
+       if (insn->modrm.nbytes) {
+               /*
+                * Interpreting the modrm byte:
+                * mod = 00 - no displacement fields (exceptions below)
+                * mod = 01 - 1-byte displacement field
+                * mod = 10 - displacement field is 4 bytes, or 2 bytes if
+                *      address size = 2 (0x67 prefix in 32-bit mode)
+                * mod = 11 - no memory operand
+                *
+                * If address size = 2...
+                * mod = 00, r/m = 110 - displacement field is 2 bytes
+                *
+                * If address size != 2...
+                * mod != 11, r/m = 100 - SIB byte exists
+                * mod = 00, SIB base = 101 - displacement field is 4 bytes
+                * mod = 00, r/m = 101 - rip-relative addressing, displacement
+                *      field is 4 bytes
+                */
+               mod = X86_MODRM_MOD(insn->modrm.value);
+               rm = X86_MODRM_RM(insn->modrm.value);
+               base = X86_SIB_BASE(insn->sib.value);
+               if (mod == 3)
+                       goto out;
+               if (mod == 1) {
+                       insn->displacement.value = get_next(char, insn);
+                       insn->displacement.nbytes = 1;
+               } else if (insn->addr_bytes == 2) {
+                       if ((mod == 0 && rm == 6) || mod == 2) {
+                               insn->displacement.value =
+                                        get_next(short, insn);
+                               insn->displacement.nbytes = 2;
+                       }
+               } else {
+                       if ((mod == 0 && rm == 5) || mod == 2 ||
+                           (mod == 0 && base == 5)) {
+                               insn->displacement.value = get_next(int, insn);
+                               insn->displacement.nbytes = 4;
+                       }
+               }
+       }
+out:
+       insn->displacement.got = 1;
+
+err_out:
+       return;
+}
+
+/* Decode moffset16/32/64. Return 0 if failed */
+static int __get_moffset(struct insn *insn)
+{
+       switch (insn->addr_bytes) {
+       case 2:
+               insn->moffset1.value = get_next(short, insn);
+               insn->moffset1.nbytes = 2;
+               break;
+       case 4:
+               insn->moffset1.value = get_next(int, insn);
+               insn->moffset1.nbytes = 4;
+               break;
+       case 8:
+               insn->moffset1.value = get_next(int, insn);
+               insn->moffset1.nbytes = 4;
+               insn->moffset2.value = get_next(int, insn);
+               insn->moffset2.nbytes = 4;
+               break;
+       default:        /* opnd_bytes must be modified manually */
+               goto err_out;
+       }
+       insn->moffset1.got = insn->moffset2.got = 1;
+
+       return 1;
+
+err_out:
+       return 0;
+}
+
+/* Decode imm v32(Iz). Return 0 if failed */
+static int __get_immv32(struct insn *insn)
+{
+       switch (insn->opnd_bytes) {
+       case 2:
+               insn->immediate.value = get_next(short, insn);
+               insn->immediate.nbytes = 2;
+               break;
+       case 4:
+       case 8:
+               insn->immediate.value = get_next(int, insn);
+               insn->immediate.nbytes = 4;
+               break;
+       default:        /* opnd_bytes must be modified manually */
+               goto err_out;
+       }
+
+       return 1;
+
+err_out:
+       return 0;
+}
+
+/* Decode imm v64(Iv/Ov), Return 0 if failed */
+static int __get_immv(struct insn *insn)
+{
+       switch (insn->opnd_bytes) {
+       case 2:
+               insn->immediate1.value = get_next(short, insn);
+               insn->immediate1.nbytes = 2;
+               break;
+       case 4:
+               insn->immediate1.value = get_next(int, insn);
+               insn->immediate1.nbytes = 4;
+               break;
+       case 8:
+               insn->immediate1.value = get_next(int, insn);
+               insn->immediate1.nbytes = 4;
+               insn->immediate2.value = get_next(int, insn);
+               insn->immediate2.nbytes = 4;
+               break;
+       default:        /* opnd_bytes must be modified manually */
+               goto err_out;
+       }
+       insn->immediate1.got = insn->immediate2.got = 1;
+
+       return 1;
+err_out:
+       return 0;
+}
+
+/* Decode ptr16:16/32(Ap) */
+static int __get_immptr(struct insn *insn)
+{
+       switch (insn->opnd_bytes) {
+       case 2:
+               insn->immediate1.value = get_next(short, insn);
+               insn->immediate1.nbytes = 2;
+               break;
+       case 4:
+               insn->immediate1.value = get_next(int, insn);
+               insn->immediate1.nbytes = 4;
+               break;
+       case 8:
+               /* ptr16:64 is not exist (no segment) */
+               return 0;
+       default:        /* opnd_bytes must be modified manually */
+               goto err_out;
+       }
+       insn->immediate2.value = get_next(unsigned short, insn);
+       insn->immediate2.nbytes = 2;
+       insn->immediate1.got = insn->immediate2.got = 1;
+
+       return 1;
+err_out:
+       return 0;
+}
+
+/**
+ * insn_get_immediate() - Get the immediates of instruction
+ * @insn:      &struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * displacement bytes.
+ * Basically, most of immediates are sign-expanded. Unsigned-value can be
+ * get by bit masking with ((1 << (nbytes * 8)) - 1)
+ */
+void insn_get_immediate(struct insn *insn)
+{
+       if (insn->immediate.got)
+               return;
+       if (!insn->displacement.got)
+               insn_get_displacement(insn);
+
+       if (inat_has_moffset(insn->attr)) {
+               if (!__get_moffset(insn))
+                       goto err_out;
+               goto done;
+       }
+
+       if (!inat_has_immediate(insn->attr))
+               /* no immediates */
+               goto done;
+
+       switch (inat_immediate_size(insn->attr)) {
+       case INAT_IMM_BYTE:
+               insn->immediate.value = get_next(char, insn);
+               insn->immediate.nbytes = 1;
+               break;
+       case INAT_IMM_WORD:
+               insn->immediate.value = get_next(short, insn);
+               insn->immediate.nbytes = 2;
+               break;
+       case INAT_IMM_DWORD:
+               insn->immediate.value = get_next(int, insn);
+               insn->immediate.nbytes = 4;
+               break;
+       case INAT_IMM_QWORD:
+               insn->immediate1.value = get_next(int, insn);
+               insn->immediate1.nbytes = 4;
+               insn->immediate2.value = get_next(int, insn);
+               insn->immediate2.nbytes = 4;
+               break;
+       case INAT_IMM_PTR:
+               if (!__get_immptr(insn))
+                       goto err_out;
+               break;
+       case INAT_IMM_VWORD32:
+               if (!__get_immv32(insn))
+                       goto err_out;
+               break;
+       case INAT_IMM_VWORD:
+               if (!__get_immv(insn))
+                       goto err_out;
+               break;
+       default:
+               /* Here, insn must have an immediate, but failed */
+               goto err_out;
+       }
+       if (inat_has_second_immediate(insn->attr)) {
+               insn->immediate2.value = get_next(char, insn);
+               insn->immediate2.nbytes = 1;
+       }
+done:
+       insn->immediate.got = 1;
+
+err_out:
+       return;
+}
+
+/**
+ * insn_get_length() - Get the length of instruction
+ * @insn:      &struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * immediates bytes.
+ */
+void insn_get_length(struct insn *insn)
+{
+       if (insn->length)
+               return;
+       if (!insn->immediate.got)
+               insn_get_immediate(insn);
+       insn->length = (unsigned char)((unsigned long)insn->next_byte
+                                    - (unsigned long)insn->kaddr);
+}
diff --git a/xen/include/asm-x86/hvm/emulate.h 
b/xen/include/asm-x86/hvm/emulate.h
index 00a06cc..db89184 100644
--- a/xen/include/asm-x86/hvm/emulate.h
+++ b/xen/include/asm-x86/hvm/emulate.h
@@ -37,6 +37,9 @@ struct hvm_emulate_ctxt {
 
 int hvm_emulate_one(
     struct hvm_emulate_ctxt *hvmemul_ctxt);
+int hvm_emulate_one_no_write(
+    struct hvm_emulate_ctxt *hvmemul_ctxt);
+void hvm_emulate_one_full(bool_t nowrite);
 void hvm_emulate_prepare(
     struct hvm_emulate_ctxt *hvmemul_ctxt,
     struct cpu_user_regs *regs);
@@ -45,6 +48,8 @@ void hvm_emulate_writeback(
 struct segment_register *hvmemul_get_seg_reg(
     enum x86_segment seg,
     struct hvm_emulate_ctxt *hvmemul_ctxt);
+int hvm_get_insn_length(
+    struct hvm_emulate_ctxt *hvmemul_ctxt);
 
 int hvmemul_do_pio(
     unsigned long port, unsigned long *reps, int size,
diff --git a/xen/include/asm-x86/inat.h b/xen/include/asm-x86/inat.h
new file mode 100644
index 0000000..74a2e31
--- /dev/null
+++ b/xen/include/asm-x86/inat.h
@@ -0,0 +1,221 @@
+#ifndef _ASM_X86_INAT_H
+#define _ASM_X86_INAT_H
+/*
+ * x86 instruction attributes
+ *
+ * Written by Masami Hiramatsu <mhiramat@xxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+#include <asm/inat_types.h>
+
+/*
+ * Internal bits. Don't use bitmasks directly, because these bits are
+ * unstable. You should use checking functions.
+ */
+
+#define INAT_OPCODE_TABLE_SIZE 256
+#define INAT_GROUP_TABLE_SIZE 8
+
+/* Legacy last prefixes */
+#define INAT_PFX_OPNDSZ        1       /* 0x66 */ /* LPFX1 */
+#define INAT_PFX_REPE  2       /* 0xF3 */ /* LPFX2 */
+#define INAT_PFX_REPNE 3       /* 0xF2 */ /* LPFX3 */
+/* Other Legacy prefixes */
+#define INAT_PFX_LOCK  4       /* 0xF0 */
+#define INAT_PFX_CS    5       /* 0x2E */
+#define INAT_PFX_DS    6       /* 0x3E */
+#define INAT_PFX_ES    7       /* 0x26 */
+#define INAT_PFX_FS    8       /* 0x64 */
+#define INAT_PFX_GS    9       /* 0x65 */
+#define INAT_PFX_SS    10      /* 0x36 */
+#define INAT_PFX_ADDRSZ        11      /* 0x67 */
+/* x86-64 REX prefix */
+#define INAT_PFX_REX   12      /* 0x4X */
+/* AVX VEX prefixes */
+#define INAT_PFX_VEX2  13      /* 2-bytes VEX prefix */
+#define INAT_PFX_VEX3  14      /* 3-bytes VEX prefix */
+
+#define INAT_LSTPFX_MAX        3
+#define INAT_LGCPFX_MAX        11
+
+/* Immediate size */
+#define INAT_IMM_BYTE          1
+#define INAT_IMM_WORD          2
+#define INAT_IMM_DWORD         3
+#define INAT_IMM_QWORD         4
+#define INAT_IMM_PTR           5
+#define INAT_IMM_VWORD32       6
+#define INAT_IMM_VWORD         7
+
+/* Legacy prefix */
+#define INAT_PFX_OFFS  0
+#define INAT_PFX_BITS  4
+#define INAT_PFX_MAX    ((1 << INAT_PFX_BITS) - 1)
+#define INAT_PFX_MASK  (INAT_PFX_MAX << INAT_PFX_OFFS)
+/* Escape opcodes */
+#define INAT_ESC_OFFS  (INAT_PFX_OFFS + INAT_PFX_BITS)
+#define INAT_ESC_BITS  2
+#define INAT_ESC_MAX   ((1 << INAT_ESC_BITS) - 1)
+#define INAT_ESC_MASK  (INAT_ESC_MAX << INAT_ESC_OFFS)
+/* Group opcodes (1-16) */
+#define INAT_GRP_OFFS  (INAT_ESC_OFFS + INAT_ESC_BITS)
+#define INAT_GRP_BITS  5
+#define INAT_GRP_MAX   ((1 << INAT_GRP_BITS) - 1)
+#define INAT_GRP_MASK  (INAT_GRP_MAX << INAT_GRP_OFFS)
+/* Immediates */
+#define INAT_IMM_OFFS  (INAT_GRP_OFFS + INAT_GRP_BITS)
+#define INAT_IMM_BITS  3
+#define INAT_IMM_MASK  (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
+/* Flags */
+#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
+#define INAT_MODRM     (1 << (INAT_FLAG_OFFS))
+#define INAT_FORCE64   (1 << (INAT_FLAG_OFFS + 1))
+#define INAT_SCNDIMM   (1 << (INAT_FLAG_OFFS + 2))
+#define INAT_MOFFSET   (1 << (INAT_FLAG_OFFS + 3))
+#define INAT_VARIANT   (1 << (INAT_FLAG_OFFS + 4))
+#define INAT_VEXOK     (1 << (INAT_FLAG_OFFS + 5))
+#define INAT_VEXONLY   (1 << (INAT_FLAG_OFFS + 6))
+/* Attribute making macros for attribute tables */
+#define INAT_MAKE_PREFIX(pfx)  (pfx << INAT_PFX_OFFS)
+#define INAT_MAKE_ESCAPE(esc)  (esc << INAT_ESC_OFFS)
+#define INAT_MAKE_GROUP(grp)   ((grp << INAT_GRP_OFFS) | INAT_MODRM)
+#define INAT_MAKE_IMM(imm)     (imm << INAT_IMM_OFFS)
+
+/* Attribute search APIs */
+extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
+extern int inat_get_last_prefix_id(insn_byte_t last_pfx);
+extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode,
+                                            int lpfx_id,
+                                            insn_attr_t esc_attr);
+extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm,
+                                           int lpfx_id,
+                                           insn_attr_t esc_attr);
+extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode,
+                                         insn_byte_t vex_m,
+                                         insn_byte_t vex_pp);
+
+/* Attribute checking functions */
+static inline int inat_is_legacy_prefix(insn_attr_t attr)
+{
+       attr &= INAT_PFX_MASK;
+       return attr && attr <= INAT_LGCPFX_MAX;
+}
+
+static inline int inat_is_address_size_prefix(insn_attr_t attr)
+{
+       return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
+}
+
+static inline int inat_is_operand_size_prefix(insn_attr_t attr)
+{
+       return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
+}
+
+static inline int inat_is_rex_prefix(insn_attr_t attr)
+{
+       return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
+}
+
+static inline int inat_last_prefix_id(insn_attr_t attr)
+{
+       if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
+               return 0;
+       else
+               return attr & INAT_PFX_MASK;
+}
+
+static inline int inat_is_vex_prefix(insn_attr_t attr)
+{
+       attr &= INAT_PFX_MASK;
+       return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3;
+}
+
+static inline int inat_is_vex3_prefix(insn_attr_t attr)
+{
+       return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
+}
+
+static inline int inat_is_escape(insn_attr_t attr)
+{
+       return attr & INAT_ESC_MASK;
+}
+
+static inline int inat_escape_id(insn_attr_t attr)
+{
+       return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
+}
+
+static inline int inat_is_group(insn_attr_t attr)
+{
+       return attr & INAT_GRP_MASK;
+}
+
+static inline int inat_group_id(insn_attr_t attr)
+{
+       return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
+}
+
+static inline int inat_group_common_attribute(insn_attr_t attr)
+{
+       return attr & ~INAT_GRP_MASK;
+}
+
+static inline int inat_has_immediate(insn_attr_t attr)
+{
+       return attr & INAT_IMM_MASK;
+}
+
+static inline int inat_immediate_size(insn_attr_t attr)
+{
+       return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
+}
+
+static inline int inat_has_modrm(insn_attr_t attr)
+{
+       return attr & INAT_MODRM;
+}
+
+static inline int inat_is_force64(insn_attr_t attr)
+{
+       return attr & INAT_FORCE64;
+}
+
+static inline int inat_has_second_immediate(insn_attr_t attr)
+{
+       return attr & INAT_SCNDIMM;
+}
+
+static inline int inat_has_moffset(insn_attr_t attr)
+{
+       return attr & INAT_MOFFSET;
+}
+
+static inline int inat_has_variant(insn_attr_t attr)
+{
+       return attr & INAT_VARIANT;
+}
+
+static inline int inat_accept_vex(insn_attr_t attr)
+{
+       return attr & INAT_VEXOK;
+}
+
+static inline int inat_must_vex(insn_attr_t attr)
+{
+       return attr & INAT_VEXONLY;
+}
+#endif
diff --git a/xen/include/asm-x86/inat_types.h b/xen/include/asm-x86/inat_types.h
new file mode 100644
index 0000000..cb3c20c
--- /dev/null
+++ b/xen/include/asm-x86/inat_types.h
@@ -0,0 +1,29 @@
+#ifndef _ASM_X86_INAT_TYPES_H
+#define _ASM_X86_INAT_TYPES_H
+/*
+ * x86 instruction attributes
+ *
+ * Written by Masami Hiramatsu <mhiramat@xxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* Instruction attributes */
+typedef unsigned int insn_attr_t;
+typedef unsigned char insn_byte_t;
+typedef signed int insn_value_t;
+
+#endif
diff --git a/xen/include/asm-x86/insn.h b/xen/include/asm-x86/insn.h
new file mode 100644
index 0000000..48eb30a
--- /dev/null
+++ b/xen/include/asm-x86/insn.h
@@ -0,0 +1,199 @@
+#ifndef _ASM_X86_INSN_H
+#define _ASM_X86_INSN_H
+/*
+ * x86 instruction analysis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2009
+ */
+
+/* insn_attr_t is defined in inat.h */
+#include <asm/inat.h>
+
+struct insn_field {
+       union {
+               insn_value_t value;
+               insn_byte_t bytes[4];
+       };
+       /* !0 if we've run insn_get_xxx() for this field */
+       unsigned char got;
+       unsigned char nbytes;
+};
+
+struct insn {
+       struct insn_field prefixes;     /*
+                                        * Prefixes
+                                        * prefixes.bytes[3]: last prefix
+                                        */
+       struct insn_field rex_prefix;   /* REX prefix */
+       struct insn_field vex_prefix;   /* VEX prefix */
+       struct insn_field opcode;       /*
+                                        * opcode.bytes[0]: opcode1
+                                        * opcode.bytes[1]: opcode2
+                                        * opcode.bytes[2]: opcode3
+                                        */
+       struct insn_field modrm;
+       struct insn_field sib;
+       struct insn_field displacement;
+       union {
+               struct insn_field immediate;
+               struct insn_field moffset1;     /* for 64bit MOV */
+               struct insn_field immediate1;   /* for 64bit imm or off16/32 */
+       };
+       union {
+               struct insn_field moffset2;     /* for 64bit MOV */
+               struct insn_field immediate2;   /* for 64bit imm or seg16 */
+       };
+
+       insn_attr_t attr;
+       unsigned char opnd_bytes;
+       unsigned char addr_bytes;
+       unsigned char length;
+       unsigned char x86_64;
+
+       const insn_byte_t *kaddr;       /* kernel address of insn to analyze */
+       const insn_byte_t *next_byte;
+};
+
+#define MAX_INSN_SIZE  16
+
+#define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
+#define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
+#define X86_MODRM_RM(modrm) ((modrm) & 0x07)
+
+#define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
+#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
+#define X86_SIB_BASE(sib) ((sib) & 0x07)
+
+#define X86_REX_W(rex) ((rex) & 8)
+#define X86_REX_R(rex) ((rex) & 4)
+#define X86_REX_X(rex) ((rex) & 2)
+#define X86_REX_B(rex) ((rex) & 1)
+
+/* VEX bit flags  */
+#define X86_VEX_W(vex) ((vex) & 0x80)  /* VEX3 Byte2 */
+#define X86_VEX_R(vex) ((vex) & 0x80)  /* VEX2/3 Byte1 */
+#define X86_VEX_X(vex) ((vex) & 0x40)  /* VEX3 Byte1 */
+#define X86_VEX_B(vex) ((vex) & 0x20)  /* VEX3 Byte1 */
+#define X86_VEX_L(vex) ((vex) & 0x04)  /* VEX3 Byte2, VEX2 Byte1 */
+/* VEX bit fields */
+#define X86_VEX3_M(vex)        ((vex) & 0x1f)          /* VEX3 Byte1 */
+#define X86_VEX2_M     1                       /* VEX2.M always 1 */
+#define X86_VEX_V(vex) (((vex) & 0x78) >> 3)   /* VEX3 Byte2, VEX2 Byte1 */
+#define X86_VEX_P(vex) ((vex) & 0x03)          /* VEX3 Byte2, VEX2 Byte1 */
+#define X86_VEX_M_MAX  0x1f                    /* VEX3.M Maximum value */
+
+extern void insn_init(struct insn *insn, const void *kaddr, int x86_64);
+extern void insn_get_prefixes(struct insn *insn);
+extern void insn_get_opcode(struct insn *insn);
+extern void insn_get_modrm(struct insn *insn);
+extern void insn_get_sib(struct insn *insn);
+extern void insn_get_displacement(struct insn *insn);
+extern void insn_get_immediate(struct insn *insn);
+extern void insn_get_length(struct insn *insn);
+
+/* Attribute will be determined after getting ModRM (for opcode groups) */
+static inline void insn_get_attribute(struct insn *insn)
+{
+       insn_get_modrm(insn);
+}
+
+/* Instruction uses RIP-relative addressing */
+extern int insn_rip_relative(struct insn *insn);
+
+/* Init insn for kernel text */
+static inline void kernel_insn_init(struct insn *insn, const void *kaddr)
+{
+#ifdef CONFIG_X86_64
+       insn_init(insn, kaddr, 1);
+#else /* CONFIG_X86_32 */
+       insn_init(insn, kaddr, 0);
+#endif
+}
+
+static inline int insn_is_avx(struct insn *insn)
+{
+       if (!insn->prefixes.got)
+               insn_get_prefixes(insn);
+       return (insn->vex_prefix.value != 0);
+}
+
+/* Ensure this instruction is decoded completely */
+static inline int insn_complete(struct insn *insn)
+{
+       return insn->opcode.got && insn->modrm.got && insn->sib.got &&
+               insn->displacement.got && insn->immediate.got;
+}
+
+static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
+{
+       if (insn->vex_prefix.nbytes == 2)       /* 2 bytes VEX */
+               return X86_VEX2_M;
+       else
+               return X86_VEX3_M(insn->vex_prefix.bytes[1]);
+}
+
+static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
+{
+       if (insn->vex_prefix.nbytes == 2)       /* 2 bytes VEX */
+               return X86_VEX_P(insn->vex_prefix.bytes[1]);
+       else
+               return X86_VEX_P(insn->vex_prefix.bytes[2]);
+}
+
+/* Get the last prefix id from last prefix or VEX prefix */
+static inline int insn_last_prefix_id(struct insn *insn)
+{
+       if (insn_is_avx(insn))
+               return insn_vex_p_bits(insn);   /* VEX_p is a SIMD prefix id */
+
+       if (insn->prefixes.bytes[3])
+               return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
+
+       return 0;
+}
+
+/* Offset of each field from kaddr */
+static inline int insn_offset_rex_prefix(struct insn *insn)
+{
+       return insn->prefixes.nbytes;
+}
+static inline int insn_offset_vex_prefix(struct insn *insn)
+{
+       return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
+}
+static inline int insn_offset_opcode(struct insn *insn)
+{
+       return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
+}
+static inline int insn_offset_modrm(struct insn *insn)
+{
+       return insn_offset_opcode(insn) + insn->opcode.nbytes;
+}
+static inline int insn_offset_sib(struct insn *insn)
+{
+       return insn_offset_modrm(insn) + insn->modrm.nbytes;
+}
+static inline int insn_offset_displacement(struct insn *insn)
+{
+       return insn_offset_sib(insn) + insn->sib.nbytes;
+}
+static inline int insn_offset_immediate(struct insn *insn)
+{
+       return insn_offset_displacement(insn) + insn->displacement.nbytes;
+}
+
+#endif /* _ASM_X86_INSN_H */
-- 
1.7.9.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.