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

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



On 02/07/14 14:33, Razvan Cojocaru wrote:
> 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/x86_emulate/ is the core of the emulation in Xen, and this
looks very much as if it should be part that, rather than wedged on the
side of the hypervisor.

Amongst other things, x86_emulate already contains instruction decode
tables, so it would appear that extending x86_emulate would result in
less code duplication.

~Andrew

> ---
>  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 */


_______________________________________________
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®.