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

Re: [Xen-devel] [PATCH 1/3] x86: add support for computing the instruction length


  • To: xen-devel@xxxxxxxxxxxxxxxxxxx
  • From: Mihai DonÈu <mdontu@xxxxxxxxxxxxxxx>
  • Date: Tue, 9 Sep 2014 11:47:05 +0300
  • Cc: keir@xxxxxxx, Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx>, jbeulich@xxxxxxxx
  • Comment: DomainKeys? See http://domainkeys.sourceforge.net/
  • Delivery-date: Tue, 09 Sep 2014 08:47:17 +0000
  • Domainkey-signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=bitdefender.com; b=QrbrBQHe1A/N852NMHW2MocO16y940lnKSndBjaQBEBdJvVVJM9D0toPW70c+Mb5kfkw2z0IyYjkdwwuY9YhLKublOfbR2Ag6qkpfPweBRBL2djYw5QoAZ17I/NkYtNSwWhWqial8pJ1iFejQgc5anNt/oLlsfx+e4HOOcfgk94Mhu7tSF2ESV9hDQlmi+qqHbXadan74UZ9VuOaJIAhTnPbyakE7CtMtRJ2OQZSl6t8HGFSCKph/47eSQFy6H5Y5KttS6dGFq1OFEaXqN57WnxLBdTtKEVoCzkG9PUFaIDKLGpl8je29Q/aluj1BzVirD3J9H0joKuYQ8D9QjxM3A==; h=Received:Received:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:In-Reply-To:References:Organization:MIME-Version:Content-Type:Content-Transfer-Encoding:X-BitDefender-Scanner:X-BitDefender-Spam:X-BitDefender-SpamStamp:X-BitDefender-CF-Stamp;
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>

On Tuesday 09 September 2014 05:28:02 Mihai DonÈu wrote:
> This patch adds support for computing the length of an instruction. The entire
> logic relies on a set of opcode tables generated by gen-insn-attr-x86.awk from
> x86-opcode-map.txt and a number of small helper functions. It originated in
> Linux, where it was added by Masami Hiramatsu. Since it's an almost identical
> copy, it's separated from the x86 emulator, simplifying future updates.
> 
> ---
> Changed since v1:
>   * adjusted the coding style to match the rest of xen
>   * moved the source files into x86/x86_emulate
>   * replaced inat-tables.c with x86-opcode-map.txt and gen-insn-attr-x86.awk
>     that are used to generate it
> 
> Signed-off-by: Mihai DonÈu <mdontu@xxxxxxxxxxxxxxx>

There are a couple of design issues with this code which Jan pointed
out and which I overlooked. I'm sorry, it was not intentional. I'll do
my best to address them in a following email.

>  xen/arch/x86/Makefile                       |  11 +-
>  xen/arch/x86/x86_emulate.c                  |   2 +
>  xen/arch/x86/x86_emulate/inat.c             |  98 +++
>  xen/arch/x86/x86_emulate/insn.c             | 624 ++++++++++++++++++
>  xen/arch/x86/x86_emulate/x86-opcode-map.txt | 961 
> ++++++++++++++++++++++++++++
>  xen/include/asm-x86/inat.h                  | 219 +++++++
>  xen/include/asm-x86/inat_types.h            |  29 +
>  xen/include/asm-x86/insn.h                  | 201 ++++++
>  xen/tools/gen-insn-attr-x86.awk             | 386 +++++++++++
>  9 files changed, 2529 insertions(+), 2 deletions(-)
>  create mode 100644 xen/arch/x86/x86_emulate/inat.c
>  create mode 100644 xen/arch/x86/x86_emulate/insn.c
>  create mode 100644 xen/arch/x86/x86_emulate/x86-opcode-map.txt
>  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
>  create mode 100644 xen/tools/gen-insn-attr-x86.awk
> 
> diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
> index c1e244d..63529d3 100644
> --- a/xen/arch/x86/Makefile
> +++ b/xen/arch/x86/Makefile
> @@ -62,7 +62,11 @@ obj-y += xstate.o
>  
>  obj-$(crash_debug) += gdbstub.o
>  
> -x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
> +inat_tables_script = $(BASEDIR)/tools/gen-insn-attr-x86.awk
> +inat_tables_maps = $(BASEDIR)/arch/x86/x86_emulate/x86-opcode-map.txt
> +
> +x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h \
> +     x86_emulate/inat.c x86_emulate/insn.c x86_emulate/inat-tables.c
>  
>  efi-$(x86_64) := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h -o \
>                                  -O $(BASEDIR)/include/xen/compile.h ]; then \
> @@ -165,9 +169,12 @@ boot/mkelf32: boot/mkelf32.c
>  efi/mkreloc: efi/mkreloc.c
>       $(HOSTCC) $(HOSTCFLAGS) -g -o $@ $<
>  
> +x86_emulate/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
> +     awk -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@
> +
>  .PHONY: clean
>  clean::
>       rm -f asm-offsets.s *.lds boot/*.o boot/*~ boot/core boot/mkelf32
>       rm -f $(BASEDIR)/.xen-syms.[0-9]* boot/.*.d
>       rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.o efi/.*.d efi/*.efi 
> efi/disabled efi/mkreloc
> -     rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin
> +     rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin 
> x86_emulate/inat-tables.c
> diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
> index 79b4ab3..1d43bb1 100644
> --- a/xen/arch/x86/x86_emulate.c
> +++ b/xen/arch/x86/x86_emulate.c
> @@ -22,3 +22,5 @@
>          cpu_has_amd_erratum(&current_cpu_data, AMD_ERRATUM_##nr)
>  
>  #include "x86_emulate/x86_emulate.c"
> +#include "x86_emulate/inat.c"
> +#include "x86_emulate/insn.c"
> diff --git a/xen/arch/x86/x86_emulate/inat.c b/xen/arch/x86/x86_emulate/inat.c
> new file mode 100644
> index 0000000..e4251ba
> --- /dev/null
> +++ b/xen/arch/x86/x86_emulate/inat.c
> @@ -0,0 +1,98 @@
> +/*
> + * 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/x86_emulate/insn.c b/xen/arch/x86/x86_emulate/insn.c
> new file mode 100644
> index 0000000..4d7416e
> --- /dev/null
> +++ b/xen/arch/x86/x86_emulate/insn.c
> @@ -0,0 +1,624 @@
> +/*
> + * 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/arch/x86/x86_emulate/x86-opcode-map.txt 
> b/xen/arch/x86/x86_emulate/x86-opcode-map.txt
> new file mode 100644
> index 0000000..1a2be7c
> --- /dev/null
> +++ b/xen/arch/x86/x86_emulate/x86-opcode-map.txt
> @@ -0,0 +1,961 @@
> +# x86 Opcode Maps
> +#
> +# This is (mostly) based on following documentations.
> +# - Intel(R) 64 and IA-32 Architectures Software Developer's Manual Vol.2C
> +#   (#326018-047US, June 2013)
> +#
> +#<Opcode maps>
> +# Table: table-name
> +# Referrer: escaped-name
> +# AVXcode: avx-code
> +# opcode: mnemonic|GrpXXX [operand1[,operand2...]] [(extra1)[,(extra2)...] 
> [| 2nd-mnemonic ...]
> +# (or)
> +# opcode: escape # escaped-name
> +# EndTable
> +#
> +#<group maps>
> +# GrpTable: GrpXXX
> +# reg:  mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 
> 2nd-mnemonic ...]
> +# EndTable
> +#
> +# AVX Superscripts
> +#  (v): this opcode requires VEX prefix.
> +#  (v1): this opcode only supports 128bit VEX.
> +#
> +# Last Prefix Superscripts
> +#  - (66): the last prefix is 0x66
> +#  - (F3): the last prefix is 0xF3
> +#  - (F2): the last prefix is 0xF2
> +#  - (!F3) : the last prefix is not 0xF3 (including non-last prefix case)
> +#  - (66&F2): Both 0x66 and 0xF2 prefixes are specified.
> +
> +Table: one byte opcode
> +Referrer:
> +AVXcode:
> +# 0x00 - 0x0f
> +00: ADD Eb,Gb
> +01: ADD Ev,Gv
> +02: ADD Gb,Eb
> +03: ADD Gv,Ev
> +04: ADD AL,Ib
> +05: ADD rAX,Iz
> +06: PUSH ES (i64)
> +07: POP ES (i64)
> +08: OR Eb,Gb
> +09: OR Ev,Gv
> +0a: OR Gb,Eb
> +0b: OR Gv,Ev
> +0c: OR AL,Ib
> +0d: OR rAX,Iz
> +0e: PUSH CS (i64)
> +0f: escape # 2-byte escape
> +# 0x10 - 0x1f
> +10: ADC Eb,Gb
> +11: ADC Ev,Gv
> +12: ADC Gb,Eb
> +13: ADC Gv,Ev
> +14: ADC AL,Ib
> +15: ADC rAX,Iz
> +16: PUSH SS (i64)
> +17: POP SS (i64)
> +18: SBB Eb,Gb
> +19: SBB Ev,Gv
> +1a: SBB Gb,Eb
> +1b: SBB Gv,Ev
> +1c: SBB AL,Ib
> +1d: SBB rAX,Iz
> +1e: PUSH DS (i64)
> +1f: POP DS (i64)
> +# 0x20 - 0x2f
> +20: AND Eb,Gb
> +21: AND Ev,Gv
> +22: AND Gb,Eb
> +23: AND Gv,Ev
> +24: AND AL,Ib
> +25: AND rAx,Iz
> +26: SEG=ES (Prefix)
> +27: DAA (i64)
> +28: SUB Eb,Gb
> +29: SUB Ev,Gv
> +2a: SUB Gb,Eb
> +2b: SUB Gv,Ev
> +2c: SUB AL,Ib
> +2d: SUB rAX,Iz
> +2e: SEG=CS (Prefix)
> +2f: DAS (i64)
> +# 0x30 - 0x3f
> +30: XOR Eb,Gb
> +31: XOR Ev,Gv
> +32: XOR Gb,Eb
> +33: XOR Gv,Ev
> +34: XOR AL,Ib
> +35: XOR rAX,Iz
> +36: SEG=SS (Prefix)
> +37: AAA (i64)
> +38: CMP Eb,Gb
> +39: CMP Ev,Gv
> +3a: CMP Gb,Eb
> +3b: CMP Gv,Ev
> +3c: CMP AL,Ib
> +3d: CMP rAX,Iz
> +3e: SEG=DS (Prefix)
> +3f: AAS (i64)
> +# 0x40 - 0x4f
> +40: INC eAX (i64) | REX (o64)
> +41: INC eCX (i64) | REX.B (o64)
> +42: INC eDX (i64) | REX.X (o64)
> +43: INC eBX (i64) | REX.XB (o64)
> +44: INC eSP (i64) | REX.R (o64)
> +45: INC eBP (i64) | REX.RB (o64)
> +46: INC eSI (i64) | REX.RX (o64)
> +47: INC eDI (i64) | REX.RXB (o64)
> +48: DEC eAX (i64) | REX.W (o64)
> +49: DEC eCX (i64) | REX.WB (o64)
> +4a: DEC eDX (i64) | REX.WX (o64)
> +4b: DEC eBX (i64) | REX.WXB (o64)
> +4c: DEC eSP (i64) | REX.WR (o64)
> +4d: DEC eBP (i64) | REX.WRB (o64)
> +4e: DEC eSI (i64) | REX.WRX (o64)
> +4f: DEC eDI (i64) | REX.WRXB (o64)
> +# 0x50 - 0x5f
> +50: PUSH rAX/r8 (d64)
> +51: PUSH rCX/r9 (d64)
> +52: PUSH rDX/r10 (d64)
> +53: PUSH rBX/r11 (d64)
> +54: PUSH rSP/r12 (d64)
> +55: PUSH rBP/r13 (d64)
> +56: PUSH rSI/r14 (d64)
> +57: PUSH rDI/r15 (d64)
> +58: POP rAX/r8 (d64)
> +59: POP rCX/r9 (d64)
> +5a: POP rDX/r10 (d64)
> +5b: POP rBX/r11 (d64)
> +5c: POP rSP/r12 (d64)
> +5d: POP rBP/r13 (d64)
> +5e: POP rSI/r14 (d64)
> +5f: POP rDI/r15 (d64)
> +# 0x60 - 0x6f
> +60: PUSHA/PUSHAD (i64)
> +61: POPA/POPAD (i64)
> +62: BOUND Gv,Ma (i64)
> +63: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64)
> +64: SEG=FS (Prefix)
> +65: SEG=GS (Prefix)
> +66: Operand-Size (Prefix)
> +67: Address-Size (Prefix)
> +68: PUSH Iz (d64)
> +69: IMUL Gv,Ev,Iz
> +6a: PUSH Ib (d64)
> +6b: IMUL Gv,Ev,Ib
> +6c: INS/INSB Yb,DX
> +6d: INS/INSW/INSD Yz,DX
> +6e: OUTS/OUTSB DX,Xb
> +6f: OUTS/OUTSW/OUTSD DX,Xz
> +# 0x70 - 0x7f
> +70: JO Jb
> +71: JNO Jb
> +72: JB/JNAE/JC Jb
> +73: JNB/JAE/JNC Jb
> +74: JZ/JE Jb
> +75: JNZ/JNE Jb
> +76: JBE/JNA Jb
> +77: JNBE/JA Jb
> +78: JS Jb
> +79: JNS Jb
> +7a: JP/JPE Jb
> +7b: JNP/JPO Jb
> +7c: JL/JNGE Jb
> +7d: JNL/JGE Jb
> +7e: JLE/JNG Jb
> +7f: JNLE/JG Jb
> +# 0x80 - 0x8f
> +80: Grp1 Eb,Ib (1A)
> +81: Grp1 Ev,Iz (1A)
> +82: Grp1 Eb,Ib (1A),(i64)
> +83: Grp1 Ev,Ib (1A)
> +84: TEST Eb,Gb
> +85: TEST Ev,Gv
> +86: XCHG Eb,Gb
> +87: XCHG Ev,Gv
> +88: MOV Eb,Gb
> +89: MOV Ev,Gv
> +8a: MOV Gb,Eb
> +8b: MOV Gv,Ev
> +8c: MOV Ev,Sw
> +8d: LEA Gv,M
> +8e: MOV Sw,Ew
> +8f: Grp1A (1A) | POP Ev (d64)
> +# 0x90 - 0x9f
> +90: NOP | PAUSE (F3) | XCHG r8,rAX
> +91: XCHG rCX/r9,rAX
> +92: XCHG rDX/r10,rAX
> +93: XCHG rBX/r11,rAX
> +94: XCHG rSP/r12,rAX
> +95: XCHG rBP/r13,rAX
> +96: XCHG rSI/r14,rAX
> +97: XCHG rDI/r15,rAX
> +98: CBW/CWDE/CDQE
> +99: CWD/CDQ/CQO
> +9a: CALLF Ap (i64)
> +9b: FWAIT/WAIT
> +9c: PUSHF/D/Q Fv (d64)
> +9d: POPF/D/Q Fv (d64)
> +9e: SAHF
> +9f: LAHF
> +# 0xa0 - 0xaf
> +a0: MOV AL,Ob
> +a1: MOV rAX,Ov
> +a2: MOV Ob,AL
> +a3: MOV Ov,rAX
> +a4: MOVS/B Yb,Xb
> +a5: MOVS/W/D/Q Yv,Xv
> +a6: CMPS/B Xb,Yb
> +a7: CMPS/W/D Xv,Yv
> +a8: TEST AL,Ib
> +a9: TEST rAX,Iz
> +aa: STOS/B Yb,AL
> +ab: STOS/W/D/Q Yv,rAX
> +ac: LODS/B AL,Xb
> +ad: LODS/W/D/Q rAX,Xv
> +ae: SCAS/B AL,Yb
> +# Note: The May 2011 Intel manual shows Xv for the second parameter of the
> +# next instruction but Yv is correct
> +af: SCAS/W/D/Q rAX,Yv
> +# 0xb0 - 0xbf
> +b0: MOV AL/R8L,Ib
> +b1: MOV CL/R9L,Ib
> +b2: MOV DL/R10L,Ib
> +b3: MOV BL/R11L,Ib
> +b4: MOV AH/R12L,Ib
> +b5: MOV CH/R13L,Ib
> +b6: MOV DH/R14L,Ib
> +b7: MOV BH/R15L,Ib
> +b8: MOV rAX/r8,Iv
> +b9: MOV rCX/r9,Iv
> +ba: MOV rDX/r10,Iv
> +bb: MOV rBX/r11,Iv
> +bc: MOV rSP/r12,Iv
> +bd: MOV rBP/r13,Iv
> +be: MOV rSI/r14,Iv
> +bf: MOV rDI/r15,Iv
> +# 0xc0 - 0xcf
> +c0: Grp2 Eb,Ib (1A)
> +c1: Grp2 Ev,Ib (1A)
> +c2: RETN Iw (f64)
> +c3: RETN
> +c4: LES Gz,Mp (i64) | VEX+2byte (Prefix)
> +c5: LDS Gz,Mp (i64) | VEX+1byte (Prefix)
> +c6: Grp11A Eb,Ib (1A)
> +c7: Grp11B Ev,Iz (1A)
> +c8: ENTER Iw,Ib
> +c9: LEAVE (d64)
> +ca: RETF Iw
> +cb: RETF
> +cc: INT3
> +cd: INT Ib
> +ce: INTO (i64)
> +cf: IRET/D/Q
> +# 0xd0 - 0xdf
> +d0: Grp2 Eb,1 (1A)
> +d1: Grp2 Ev,1 (1A)
> +d2: Grp2 Eb,CL (1A)
> +d3: Grp2 Ev,CL (1A)
> +d4: AAM Ib (i64)
> +d5: AAD Ib (i64)
> +d6:
> +d7: XLAT/XLATB
> +d8: ESC
> +d9: ESC
> +da: ESC
> +db: ESC
> +dc: ESC
> +dd: ESC
> +de: ESC
> +df: ESC
> +# 0xe0 - 0xef
> +e0: LOOPNE/LOOPNZ Jb (f64)
> +e1: LOOPE/LOOPZ Jb (f64)
> +e2: LOOP Jb (f64)
> +e3: JrCXZ Jb (f64)
> +e4: IN AL,Ib
> +e5: IN eAX,Ib
> +e6: OUT Ib,AL
> +e7: OUT Ib,eAX
> +e8: CALL Jz (f64)
> +e9: JMP-near Jz (f64)
> +ea: JMP-far Ap (i64)
> +eb: JMP-short Jb (f64)
> +ec: IN AL,DX
> +ed: IN eAX,DX
> +ee: OUT DX,AL
> +ef: OUT DX,eAX
> +# 0xf0 - 0xff
> +f0: LOCK (Prefix)
> +f1:
> +f2: REPNE (Prefix) | XACQUIRE (Prefix)
> +f3: REP/REPE (Prefix) | XRELEASE (Prefix)
> +f4: HLT
> +f5: CMC
> +f6: Grp3_1 Eb (1A)
> +f7: Grp3_2 Ev (1A)
> +f8: CLC
> +f9: STC
> +fa: CLI
> +fb: STI
> +fc: CLD
> +fd: STD
> +fe: Grp4 (1A)
> +ff: Grp5 (1A)
> +EndTable
> +
> +Table: 2-byte opcode (0x0f)
> +Referrer: 2-byte escape
> +AVXcode: 1
> +# 0x0f 0x00-0x0f
> +00: Grp6 (1A)
> +01: Grp7 (1A)
> +02: LAR Gv,Ew
> +03: LSL Gv,Ew
> +04:
> +05: SYSCALL (o64)
> +06: CLTS
> +07: SYSRET (o64)
> +08: INVD
> +09: WBINVD
> +0a:
> +0b: UD2 (1B)
> +0c:
> +# AMD's prefetch group. Intel supports prefetchw(/1) only.
> +0d: GrpP
> +0e: FEMMS
> +# 3DNow! uses the last imm byte as opcode extension.
> +0f: 3DNow! Pq,Qq,Ib
> +# 0x0f 0x10-0x1f
> +# NOTE: According to Intel SDM opcode map, vmovups and vmovupd has no 
> operands
> +# but it actually has operands. And also, vmovss and vmovsd only accept 
> 128bit.
> +# MOVSS/MOVSD has too many forms(3) on SDM. This map just shows a typical 
> form.
> +# Many AVX instructions lack v1 superscript, according to Intel 
> AVX-Prgramming
> +# Reference A.1
> +10: vmovups Vps,Wps | vmovupd Vpd,Wpd (66) | vmovss Vx,Hx,Wss (F3),(v1) | 
> vmovsd Vx,Hx,Wsd (F2),(v1)
> +11: vmovups Wps,Vps | vmovupd Wpd,Vpd (66) | vmovss Wss,Hx,Vss (F3),(v1) | 
> vmovsd Wsd,Hx,Vsd (F2),(v1)
> +12: vmovlps Vq,Hq,Mq (v1) | vmovhlps Vq,Hq,Uq (v1) | vmovlpd Vq,Hq,Mq 
> (66),(v1) | vmovsldup Vx,Wx (F3) | vmovddup Vx,Wx (F2)
> +13: vmovlps Mq,Vq (v1) | vmovlpd Mq,Vq (66),(v1)
> +14: vunpcklps Vx,Hx,Wx | vunpcklpd Vx,Hx,Wx (66)
> +15: vunpckhps Vx,Hx,Wx | vunpckhpd Vx,Hx,Wx (66)
> +16: vmovhps Vdq,Hq,Mq (v1) | vmovlhps Vdq,Hq,Uq (v1) | vmovhpd Vdq,Hq,Mq 
> (66),(v1) | vmovshdup Vx,Wx (F3)
> +17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1)
> +18: Grp16 (1A)
> +19:
> +1a: BNDCL Ev,Gv | BNDCU Ev,Gv | BNDMOV Gv,Ev | BNDLDX Gv,Ev,Gv
> +1b: BNDCN Ev,Gv | BNDMOV Ev,Gv | BNDMK Gv,Ev | BNDSTX Ev,GV,Gv
> +1c:
> +1d:
> +1e:
> +1f: NOP Ev
> +# 0x0f 0x20-0x2f
> +20: MOV Rd,Cd
> +21: MOV Rd,Dd
> +22: MOV Cd,Rd
> +23: MOV Dd,Rd
> +24:
> +25:
> +26:
> +27:
> +28: vmovaps Vps,Wps | vmovapd Vpd,Wpd (66)
> +29: vmovaps Wps,Vps | vmovapd Wpd,Vpd (66)
> +2a: cvtpi2ps Vps,Qpi | cvtpi2pd Vpd,Qpi (66) | vcvtsi2ss Vss,Hss,Ey 
> (F3),(v1) | vcvtsi2sd Vsd,Hsd,Ey (F2),(v1)
> +2b: vmovntps Mps,Vps | vmovntpd Mpd,Vpd (66)
> +2c: cvttps2pi Ppi,Wps | cvttpd2pi Ppi,Wpd (66) | vcvttss2si Gy,Wss (F3),(v1) 
> | vcvttsd2si Gy,Wsd (F2),(v1)
> +2d: cvtps2pi Ppi,Wps | cvtpd2pi Qpi,Wpd (66) | vcvtss2si Gy,Wss (F3),(v1) | 
> vcvtsd2si Gy,Wsd (F2),(v1)
> +2e: vucomiss Vss,Wss (v1) | vucomisd  Vsd,Wsd (66),(v1)
> +2f: vcomiss Vss,Wss (v1) | vcomisd  Vsd,Wsd (66),(v1)
> +# 0x0f 0x30-0x3f
> +30: WRMSR
> +31: RDTSC
> +32: RDMSR
> +33: RDPMC
> +34: SYSENTER
> +35: SYSEXIT
> +36:
> +37: GETSEC
> +38: escape # 3-byte escape 1
> +39:
> +3a: escape # 3-byte escape 2
> +3b:
> +3c:
> +3d:
> +3e:
> +3f:
> +# 0x0f 0x40-0x4f
> +40: CMOVO Gv,Ev
> +41: CMOVNO Gv,Ev
> +42: CMOVB/C/NAE Gv,Ev
> +43: CMOVAE/NB/NC Gv,Ev
> +44: CMOVE/Z Gv,Ev
> +45: CMOVNE/NZ Gv,Ev
> +46: CMOVBE/NA Gv,Ev
> +47: CMOVA/NBE Gv,Ev
> +48: CMOVS Gv,Ev
> +49: CMOVNS Gv,Ev
> +4a: CMOVP/PE Gv,Ev
> +4b: CMOVNP/PO Gv,Ev
> +4c: CMOVL/NGE Gv,Ev
> +4d: CMOVNL/GE Gv,Ev
> +4e: CMOVLE/NG Gv,Ev
> +4f: CMOVNLE/G Gv,Ev
> +# 0x0f 0x50-0x5f
> +50: vmovmskps Gy,Ups | vmovmskpd Gy,Upd (66)
> +51: vsqrtps Vps,Wps | vsqrtpd Vpd,Wpd (66) | vsqrtss Vss,Hss,Wss (F3),(v1) | 
> vsqrtsd Vsd,Hsd,Wsd (F2),(v1)
> +52: vrsqrtps Vps,Wps | vrsqrtss Vss,Hss,Wss (F3),(v1)
> +53: vrcpps Vps,Wps | vrcpss Vss,Hss,Wss (F3),(v1)
> +54: vandps Vps,Hps,Wps | vandpd Vpd,Hpd,Wpd (66)
> +55: vandnps Vps,Hps,Wps | vandnpd Vpd,Hpd,Wpd (66)
> +56: vorps Vps,Hps,Wps | vorpd Vpd,Hpd,Wpd (66)
> +57: vxorps Vps,Hps,Wps | vxorpd Vpd,Hpd,Wpd (66)
> +58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss 
> (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1)
> +59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss 
> (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1)
> +5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss 
> (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1)
> +5b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3)
> +5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss 
> (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1)
> +5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss 
> (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1)
> +5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss 
> (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1)
> +5f: vmaxps Vps,Hps,Wps | vmaxpd Vpd,Hpd,Wpd (66) | vmaxss Vss,Hss,Wss 
> (F3),(v1) | vmaxsd Vsd,Hsd,Wsd (F2),(v1)
> +# 0x0f 0x60-0x6f
> +60: punpcklbw Pq,Qd | vpunpcklbw Vx,Hx,Wx (66),(v1)
> +61: punpcklwd Pq,Qd | vpunpcklwd Vx,Hx,Wx (66),(v1)
> +62: punpckldq Pq,Qd | vpunpckldq Vx,Hx,Wx (66),(v1)
> +63: packsswb Pq,Qq | vpacksswb Vx,Hx,Wx (66),(v1)
> +64: pcmpgtb Pq,Qq | vpcmpgtb Vx,Hx,Wx (66),(v1)
> +65: pcmpgtw Pq,Qq | vpcmpgtw Vx,Hx,Wx (66),(v1)
> +66: pcmpgtd Pq,Qq | vpcmpgtd Vx,Hx,Wx (66),(v1)
> +67: packuswb Pq,Qq | vpackuswb Vx,Hx,Wx (66),(v1)
> +68: punpckhbw Pq,Qd | vpunpckhbw Vx,Hx,Wx (66),(v1)
> +69: punpckhwd Pq,Qd | vpunpckhwd Vx,Hx,Wx (66),(v1)
> +6a: punpckhdq Pq,Qd | vpunpckhdq Vx,Hx,Wx (66),(v1)
> +6b: packssdw Pq,Qd | vpackssdw Vx,Hx,Wx (66),(v1)
> +6c: vpunpcklqdq Vx,Hx,Wx (66),(v1)
> +6d: vpunpckhqdq Vx,Hx,Wx (66),(v1)
> +6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1)
> +6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3)
> +# 0x0f 0x70-0x7f
> +70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib 
> (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1)
> +71: Grp12 (1A)
> +72: Grp13 (1A)
> +73: Grp14 (1A)
> +74: pcmpeqb Pq,Qq | vpcmpeqb Vx,Hx,Wx (66),(v1)
> +75: pcmpeqw Pq,Qq | vpcmpeqw Vx,Hx,Wx (66),(v1)
> +76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1)
> +# Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX.
> +77: emms | vzeroupper | vzeroall
> +78: VMREAD Ey,Gy
> +79: VMWRITE Gy,Ey
> +7a:
> +7b:
> +7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2)
> +7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2)
> +7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1)
> +7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3)
> +# 0x0f 0x80-0x8f
> +80: JO Jz (f64)
> +81: JNO Jz (f64)
> +82: JB/JC/JNAE Jz (f64)
> +83: JAE/JNB/JNC Jz (f64)
> +84: JE/JZ Jz (f64)
> +85: JNE/JNZ Jz (f64)
> +86: JBE/JNA Jz (f64)
> +87: JA/JNBE Jz (f64)
> +88: JS Jz (f64)
> +89: JNS Jz (f64)
> +8a: JP/JPE Jz (f64)
> +8b: JNP/JPO Jz (f64)
> +8c: JL/JNGE Jz (f64)
> +8d: JNL/JGE Jz (f64)
> +8e: JLE/JNG Jz (f64)
> +8f: JNLE/JG Jz (f64)
> +# 0x0f 0x90-0x9f
> +90: SETO Eb
> +91: SETNO Eb
> +92: SETB/C/NAE Eb
> +93: SETAE/NB/NC Eb
> +94: SETE/Z Eb
> +95: SETNE/NZ Eb
> +96: SETBE/NA Eb
> +97: SETA/NBE Eb
> +98: SETS Eb
> +99: SETNS Eb
> +9a: SETP/PE Eb
> +9b: SETNP/PO Eb
> +9c: SETL/NGE Eb
> +9d: SETNL/GE Eb
> +9e: SETLE/NG Eb
> +9f: SETNLE/G Eb
> +# 0x0f 0xa0-0xaf
> +a0: PUSH FS (d64)
> +a1: POP FS (d64)
> +a2: CPUID
> +a3: BT Ev,Gv
> +a4: SHLD Ev,Gv,Ib
> +a5: SHLD Ev,Gv,CL
> +a6: GrpPDLK
> +a7: GrpRNG
> +a8: PUSH GS (d64)
> +a9: POP GS (d64)
> +aa: RSM
> +ab: BTS Ev,Gv
> +ac: SHRD Ev,Gv,Ib
> +ad: SHRD Ev,Gv,CL
> +ae: Grp15 (1A),(1C)
> +af: IMUL Gv,Ev
> +# 0x0f 0xb0-0xbf
> +b0: CMPXCHG Eb,Gb
> +b1: CMPXCHG Ev,Gv
> +b2: LSS Gv,Mp
> +b3: BTR Ev,Gv
> +b4: LFS Gv,Mp
> +b5: LGS Gv,Mp
> +b6: MOVZX Gv,Eb
> +b7: MOVZX Gv,Ew
> +b8: JMPE (!F3) | POPCNT Gv,Ev (F3)
> +b9: Grp10 (1A)
> +ba: Grp8 Ev,Ib (1A)
> +bb: BTC Ev,Gv
> +bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3)
> +bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3)
> +be: MOVSX Gv,Eb
> +bf: MOVSX Gv,Ew
> +# 0x0f 0xc0-0xcf
> +c0: XADD Eb,Gb
> +c1: XADD Ev,Gv
> +c2: vcmpps Vps,Hps,Wps,Ib | vcmppd Vpd,Hpd,Wpd,Ib (66) | vcmpss 
> Vss,Hss,Wss,Ib (F3),(v1) | vcmpsd Vsd,Hsd,Wsd,Ib (F2),(v1)
> +c3: movnti My,Gy
> +c4: pinsrw Pq,Ry/Mw,Ib | vpinsrw Vdq,Hdq,Ry/Mw,Ib (66),(v1)
> +c5: pextrw Gd,Nq,Ib | vpextrw Gd,Udq,Ib (66),(v1)
> +c6: vshufps Vps,Hps,Wps,Ib | vshufpd Vpd,Hpd,Wpd,Ib (66)
> +c7: Grp9 (1A)
> +c8: BSWAP RAX/EAX/R8/R8D
> +c9: BSWAP RCX/ECX/R9/R9D
> +ca: BSWAP RDX/EDX/R10/R10D
> +cb: BSWAP RBX/EBX/R11/R11D
> +cc: BSWAP RSP/ESP/R12/R12D
> +cd: BSWAP RBP/EBP/R13/R13D
> +ce: BSWAP RSI/ESI/R14/R14D
> +cf: BSWAP RDI/EDI/R15/R15D
> +# 0x0f 0xd0-0xdf
> +d0: vaddsubpd Vpd,Hpd,Wpd (66) | vaddsubps Vps,Hps,Wps (F2)
> +d1: psrlw Pq,Qq | vpsrlw Vx,Hx,Wx (66),(v1)
> +d2: psrld Pq,Qq | vpsrld Vx,Hx,Wx (66),(v1)
> +d3: psrlq Pq,Qq | vpsrlq Vx,Hx,Wx (66),(v1)
> +d4: paddq Pq,Qq | vpaddq Vx,Hx,Wx (66),(v1)
> +d5: pmullw Pq,Qq | vpmullw Vx,Hx,Wx (66),(v1)
> +d6: vmovq Wq,Vq (66),(v1) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2)
> +d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1)
> +d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1)
> +d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1)
> +da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1)
> +db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1)
> +dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1)
> +dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1)
> +de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1)
> +df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1)
> +# 0x0f 0xe0-0xef
> +e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1)
> +e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1)
> +e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1)
> +e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1)
> +e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1)
> +e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1)
> +e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2)
> +e7: movntq Mq,Pq | vmovntdq Mx,Vx (66)
> +e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1)
> +e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1)
> +ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1)
> +eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1)
> +ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1)
> +ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1)
> +ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1)
> +ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1)
> +# 0x0f 0xf0-0xff
> +f0: vlddqu Vx,Mx (F2)
> +f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1)
> +f2: pslld Pq,Qq | vpslld Vx,Hx,Wx (66),(v1)
> +f3: psllq Pq,Qq | vpsllq Vx,Hx,Wx (66),(v1)
> +f4: pmuludq Pq,Qq | vpmuludq Vx,Hx,Wx (66),(v1)
> +f5: pmaddwd Pq,Qq | vpmaddwd Vx,Hx,Wx (66),(v1)
> +f6: psadbw Pq,Qq | vpsadbw Vx,Hx,Wx (66),(v1)
> +f7: maskmovq Pq,Nq | vmaskmovdqu Vx,Ux (66),(v1)
> +f8: psubb Pq,Qq | vpsubb Vx,Hx,Wx (66),(v1)
> +f9: psubw Pq,Qq | vpsubw Vx,Hx,Wx (66),(v1)
> +fa: psubd Pq,Qq | vpsubd Vx,Hx,Wx (66),(v1)
> +fb: psubq Pq,Qq | vpsubq Vx,Hx,Wx (66),(v1)
> +fc: paddb Pq,Qq | vpaddb Vx,Hx,Wx (66),(v1)
> +fd: paddw Pq,Qq | vpaddw Vx,Hx,Wx (66),(v1)
> +fe: paddd Pq,Qq | vpaddd Vx,Hx,Wx (66),(v1)
> +ff:
> +EndTable
> +
> +Table: 3-byte opcode 1 (0x0f 0x38)
> +Referrer: 3-byte escape 1
> +AVXcode: 2
> +# 0x0f 0x38 0x00-0x0f
> +00: pshufb Pq,Qq | vpshufb Vx,Hx,Wx (66),(v1)
> +01: phaddw Pq,Qq | vphaddw Vx,Hx,Wx (66),(v1)
> +02: phaddd Pq,Qq | vphaddd Vx,Hx,Wx (66),(v1)
> +03: phaddsw Pq,Qq | vphaddsw Vx,Hx,Wx (66),(v1)
> +04: pmaddubsw Pq,Qq | vpmaddubsw Vx,Hx,Wx (66),(v1)
> +05: phsubw Pq,Qq | vphsubw Vx,Hx,Wx (66),(v1)
> +06: phsubd Pq,Qq | vphsubd Vx,Hx,Wx (66),(v1)
> +07: phsubsw Pq,Qq | vphsubsw Vx,Hx,Wx (66),(v1)
> +08: psignb Pq,Qq | vpsignb Vx,Hx,Wx (66),(v1)
> +09: psignw Pq,Qq | vpsignw Vx,Hx,Wx (66),(v1)
> +0a: psignd Pq,Qq | vpsignd Vx,Hx,Wx (66),(v1)
> +0b: pmulhrsw Pq,Qq | vpmulhrsw Vx,Hx,Wx (66),(v1)
> +0c: vpermilps Vx,Hx,Wx (66),(v)
> +0d: vpermilpd Vx,Hx,Wx (66),(v)
> +0e: vtestps Vx,Wx (66),(v)
> +0f: vtestpd Vx,Wx (66),(v)
> +# 0x0f 0x38 0x10-0x1f
> +10: pblendvb Vdq,Wdq (66)
> +11:
> +12:
> +13: vcvtph2ps Vx,Wx,Ib (66),(v)
> +14: blendvps Vdq,Wdq (66)
> +15: blendvpd Vdq,Wdq (66)
> +16: vpermps Vqq,Hqq,Wqq (66),(v)
> +17: vptest Vx,Wx (66)
> +18: vbroadcastss Vx,Wd (66),(v)
> +19: vbroadcastsd Vqq,Wq (66),(v)
> +1a: vbroadcastf128 Vqq,Mdq (66),(v)
> +1b:
> +1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1)
> +1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1)
> +1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1)
> +1f:
> +# 0x0f 0x38 0x20-0x2f
> +20: vpmovsxbw Vx,Ux/Mq (66),(v1)
> +21: vpmovsxbd Vx,Ux/Md (66),(v1)
> +22: vpmovsxbq Vx,Ux/Mw (66),(v1)
> +23: vpmovsxwd Vx,Ux/Mq (66),(v1)
> +24: vpmovsxwq Vx,Ux/Md (66),(v1)
> +25: vpmovsxdq Vx,Ux/Mq (66),(v1)
> +26:
> +27:
> +28: vpmuldq Vx,Hx,Wx (66),(v1)
> +29: vpcmpeqq Vx,Hx,Wx (66),(v1)
> +2a: vmovntdqa Vx,Mx (66),(v1)
> +2b: vpackusdw Vx,Hx,Wx (66),(v1)
> +2c: vmaskmovps Vx,Hx,Mx (66),(v)
> +2d: vmaskmovpd Vx,Hx,Mx (66),(v)
> +2e: vmaskmovps Mx,Hx,Vx (66),(v)
> +2f: vmaskmovpd Mx,Hx,Vx (66),(v)
> +# 0x0f 0x38 0x30-0x3f
> +30: vpmovzxbw Vx,Ux/Mq (66),(v1)
> +31: vpmovzxbd Vx,Ux/Md (66),(v1)
> +32: vpmovzxbq Vx,Ux/Mw (66),(v1)
> +33: vpmovzxwd Vx,Ux/Mq (66),(v1)
> +34: vpmovzxwq Vx,Ux/Md (66),(v1)
> +35: vpmovzxdq Vx,Ux/Mq (66),(v1)
> +36: vpermd Vqq,Hqq,Wqq (66),(v)
> +37: vpcmpgtq Vx,Hx,Wx (66),(v1)
> +38: vpminsb Vx,Hx,Wx (66),(v1)
> +39: vpminsd Vx,Hx,Wx (66),(v1)
> +3a: vpminuw Vx,Hx,Wx (66),(v1)
> +3b: vpminud Vx,Hx,Wx (66),(v1)
> +3c: vpmaxsb Vx,Hx,Wx (66),(v1)
> +3d: vpmaxsd Vx,Hx,Wx (66),(v1)
> +3e: vpmaxuw Vx,Hx,Wx (66),(v1)
> +3f: vpmaxud Vx,Hx,Wx (66),(v1)
> +# 0x0f 0x38 0x40-0x8f
> +40: vpmulld Vx,Hx,Wx (66),(v1)
> +41: vphminposuw Vdq,Wdq (66),(v1)
> +42:
> +43:
> +44:
> +45: vpsrlvd/q Vx,Hx,Wx (66),(v)
> +46: vpsravd Vx,Hx,Wx (66),(v)
> +47: vpsllvd/q Vx,Hx,Wx (66),(v)
> +# Skip 0x48-0x57
> +58: vpbroadcastd Vx,Wx (66),(v)
> +59: vpbroadcastq Vx,Wx (66),(v)
> +5a: vbroadcasti128 Vqq,Mdq (66),(v)
> +# Skip 0x5b-0x77
> +78: vpbroadcastb Vx,Wx (66),(v)
> +79: vpbroadcastw Vx,Wx (66),(v)
> +# Skip 0x7a-0x7f
> +80: INVEPT Gy,Mdq (66)
> +81: INVPID Gy,Mdq (66)
> +82: INVPCID Gy,Mdq (66)
> +8c: vpmaskmovd/q Vx,Hx,Mx (66),(v)
> +8e: vpmaskmovd/q Mx,Vx,Hx (66),(v)
> +# 0x0f 0x38 0x90-0xbf (FMA)
> +90: vgatherdd/q Vx,Hx,Wx (66),(v)
> +91: vgatherqd/q Vx,Hx,Wx (66),(v)
> +92: vgatherdps/d Vx,Hx,Wx (66),(v)
> +93: vgatherqps/d Vx,Hx,Wx (66),(v)
> +94:
> +95:
> +96: vfmaddsub132ps/d Vx,Hx,Wx (66),(v)
> +97: vfmsubadd132ps/d Vx,Hx,Wx (66),(v)
> +98: vfmadd132ps/d Vx,Hx,Wx (66),(v)
> +99: vfmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
> +9a: vfmsub132ps/d Vx,Hx,Wx (66),(v)
> +9b: vfmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
> +9c: vfnmadd132ps/d Vx,Hx,Wx (66),(v)
> +9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
> +9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v)
> +9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
> +a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v)
> +a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v)
> +a8: vfmadd213ps/d Vx,Hx,Wx (66),(v)
> +a9: vfmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
> +aa: vfmsub213ps/d Vx,Hx,Wx (66),(v)
> +ab: vfmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
> +ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v)
> +ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
> +ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v)
> +af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
> +b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v)
> +b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v)
> +b8: vfmadd231ps/d Vx,Hx,Wx (66),(v)
> +b9: vfmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
> +ba: vfmsub231ps/d Vx,Hx,Wx (66),(v)
> +bb: vfmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
> +bc: vfnmadd231ps/d Vx,Hx,Wx (66),(v)
> +bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
> +be: vfnmsub231ps/d Vx,Hx,Wx (66),(v)
> +bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
> +# 0x0f 0x38 0xc0-0xff
> +db: VAESIMC Vdq,Wdq (66),(v1)
> +dc: VAESENC Vdq,Hdq,Wdq (66),(v1)
> +dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1)
> +de: VAESDEC Vdq,Hdq,Wdq (66),(v1)
> +df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1)
> +f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) | CRC32 Gd,Eb (66&F2)
> +f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) | CRC32 Gd,Ew (66&F2)
> +f2: ANDN Gy,By,Ey (v)
> +f3: Grp17 (1A)
> +f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v)
> +f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v)
> +f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | 
> SHRX Gy,Ey,By (F2),(v)
> +EndTable
> +
> +Table: 3-byte opcode 2 (0x0f 0x3a)
> +Referrer: 3-byte escape 2
> +AVXcode: 3
> +# 0x0f 0x3a 0x00-0xff
> +00: vpermq Vqq,Wqq,Ib (66),(v)
> +01: vpermpd Vqq,Wqq,Ib (66),(v)
> +02: vpblendd Vx,Hx,Wx,Ib (66),(v)
> +03:
> +04: vpermilps Vx,Wx,Ib (66),(v)
> +05: vpermilpd Vx,Wx,Ib (66),(v)
> +06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v)
> +07:
> +08: vroundps Vx,Wx,Ib (66)
> +09: vroundpd Vx,Wx,Ib (66)
> +0a: vroundss Vss,Wss,Ib (66),(v1)
> +0b: vroundsd Vsd,Wsd,Ib (66),(v1)
> +0c: vblendps Vx,Hx,Wx,Ib (66)
> +0d: vblendpd Vx,Hx,Wx,Ib (66)
> +0e: vpblendw Vx,Hx,Wx,Ib (66),(v1)
> +0f: palignr Pq,Qq,Ib | vpalignr Vx,Hx,Wx,Ib (66),(v1)
> +14: vpextrb Rd/Mb,Vdq,Ib (66),(v1)
> +15: vpextrw Rd/Mw,Vdq,Ib (66),(v1)
> +16: vpextrd/q Ey,Vdq,Ib (66),(v1)
> +17: vextractps Ed,Vdq,Ib (66),(v1)
> +18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v)
> +19: vextractf128 Wdq,Vqq,Ib (66),(v)
> +1d: vcvtps2ph Wx,Vx,Ib (66),(v)
> +20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1)
> +21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1)
> +22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1)
> +38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v)
> +39: vextracti128 Wdq,Vqq,Ib (66),(v)
> +40: vdpps Vx,Hx,Wx,Ib (66)
> +41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1)
> +42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1)
> +44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1)
> +46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v)
> +4a: vblendvps Vx,Hx,Wx,Lx (66),(v)
> +4b: vblendvpd Vx,Hx,Wx,Lx (66),(v)
> +4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1)
> +60: vpcmpestrm Vdq,Wdq,Ib (66),(v1)
> +61: vpcmpestri Vdq,Wdq,Ib (66),(v1)
> +62: vpcmpistrm Vdq,Wdq,Ib (66),(v1)
> +63: vpcmpistri Vdq,Wdq,Ib (66),(v1)
> +df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1)
> +f0: RORX Gy,Ey,Ib (F2),(v)
> +EndTable
> +
> +GrpTable: Grp1
> +0: ADD
> +1: OR
> +2: ADC
> +3: SBB
> +4: AND
> +5: SUB
> +6: XOR
> +7: CMP
> +EndTable
> +
> +GrpTable: Grp1A
> +0: POP
> +EndTable
> +
> +GrpTable: Grp2
> +0: ROL
> +1: ROR
> +2: RCL
> +3: RCR
> +4: SHL/SAL
> +5: SHR
> +6:
> +7: SAR
> +EndTable
> +
> +GrpTable: Grp3_1
> +0: TEST Eb,Ib
> +1:
> +2: NOT Eb
> +3: NEG Eb
> +4: MUL AL,Eb
> +5: IMUL AL,Eb
> +6: DIV AL,Eb
> +7: IDIV AL,Eb
> +EndTable
> +
> +GrpTable: Grp3_2
> +0: TEST Ev,Iz
> +1:
> +2: NOT Ev
> +3: NEG Ev
> +4: MUL rAX,Ev
> +5: IMUL rAX,Ev
> +6: DIV rAX,Ev
> +7: IDIV rAX,Ev
> +EndTable
> +
> +GrpTable: Grp4
> +0: INC Eb
> +1: DEC Eb
> +EndTable
> +
> +GrpTable: Grp5
> +0: INC Ev
> +1: DEC Ev
> +2: CALLN Ev (f64)
> +3: CALLF Ep
> +4: JMPN Ev (f64)
> +5: JMPF Mp
> +6: PUSH Ev (d64)
> +7:
> +EndTable
> +
> +GrpTable: Grp6
> +0: SLDT Rv/Mw
> +1: STR Rv/Mw
> +2: LLDT Ew
> +3: LTR Ew
> +4: VERR Ew
> +5: VERW Ew
> +EndTable
> +
> +GrpTable: Grp7
> +0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME 
> (011),(11B) | VMXOFF (100),(11B)
> +1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | 
> STAC (011),(11B)
> +2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | 
> XEND (101)(11B) | XTEST (110)(11B)
> +3: LIDT Ms
> +4: SMSW Mw/Rv
> +5:
> +6: LMSW Ew
> +7: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B)
> +EndTable
> +
> +GrpTable: Grp8
> +4: BT
> +5: BTS
> +6: BTR
> +7: BTC
> +EndTable
> +
> +GrpTable: Grp9
> +1: CMPXCHG8B/16B Mq/Mdq
> +6: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B)
> +7: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B)
> +EndTable
> +
> +GrpTable: Grp10
> +EndTable
> +
> +# Grp11A and Grp11B are expressed as Grp11 in Intel SDM
> +GrpTable: Grp11A
> +0: MOV Eb,Ib
> +7: XABORT Ib (000),(11B)
> +EndTable
> +
> +GrpTable: Grp11B
> +0: MOV Eb,Iz
> +7: XBEGIN Jz (000),(11B)
> +EndTable
> +
> +GrpTable: Grp12
> +2: psrlw Nq,Ib (11B) | vpsrlw Hx,Ux,Ib (66),(11B),(v1)
> +4: psraw Nq,Ib (11B) | vpsraw Hx,Ux,Ib (66),(11B),(v1)
> +6: psllw Nq,Ib (11B) | vpsllw Hx,Ux,Ib (66),(11B),(v1)
> +EndTable
> +
> +GrpTable: Grp13
> +2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1)
> +4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1)
> +6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1)
> +EndTable
> +
> +GrpTable: Grp14
> +2: psrlq Nq,Ib (11B) | vpsrlq Hx,Ux,Ib (66),(11B),(v1)
> +3: vpsrldq Hx,Ux,Ib (66),(11B),(v1)
> +6: psllq Nq,Ib (11B) | vpsllq Hx,Ux,Ib (66),(11B),(v1)
> +7: vpslldq Hx,Ux,Ib (66),(11B),(v1)
> +EndTable
> +
> +GrpTable: Grp15
> +0: fxsave | RDFSBASE Ry (F3),(11B)
> +1: fxstor | RDGSBASE Ry (F3),(11B)
> +2: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B)
> +3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
> +4: XSAVE
> +5: XRSTOR | lfence (11B)
> +6: XSAVEOPT | mfence (11B)
> +7: clflush | sfence (11B)
> +EndTable
> +
> +GrpTable: Grp16
> +0: prefetch NTA
> +1: prefetch T0
> +2: prefetch T1
> +3: prefetch T2
> +EndTable
> +
> +GrpTable: Grp17
> +1: BLSR By,Ey (v)
> +2: BLSMSK By,Ey (v)
> +3: BLSI By,Ey (v)
> +EndTable
> +
> +# AMD's Prefetch Group
> +GrpTable: GrpP
> +0: PREFETCH
> +1: PREFETCHW
> +EndTable
> +
> +GrpTable: GrpPDLK
> +0: MONTMUL
> +1: XSHA1
> +2: XSHA2
> +EndTable
> +
> +GrpTable: GrpRNG
> +0: xstore-rng
> +1: xcrypt-ecb
> +2: xcrypt-cbc
> +4: xcrypt-cfb
> +5: xcrypt-ofb
> +EndTable
> diff --git a/xen/include/asm-x86/inat.h b/xen/include/asm-x86/inat.h
> new file mode 100644
> index 0000000..41b9066
> --- /dev/null
> +++ b/xen/include/asm-x86/inat.h
> @@ -0,0 +1,219 @@
> +#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 /* _ASM_X86_INAT_H */
> diff --git a/xen/include/asm-x86/inat_types.h 
> b/xen/include/asm-x86/inat_types.h
> new file mode 100644
> index 0000000..662ac14
> --- /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 /* _ASM_X86_INAT_TYPES_H */
> diff --git a/xen/include/asm-x86/insn.h b/xen/include/asm-x86/insn.h
> new file mode 100644
> index 0000000..739773a
> --- /dev/null
> +++ b/xen/include/asm-x86/insn.h
> @@ -0,0 +1,201 @@
> +#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 */
> diff --git a/xen/tools/gen-insn-attr-x86.awk b/xen/tools/gen-insn-attr-x86.awk
> new file mode 100644
> index 0000000..bbb8f40
> --- /dev/null
> +++ b/xen/tools/gen-insn-attr-x86.awk
> @@ -0,0 +1,386 @@
> +#!/bin/awk -f
> +# gen-insn-attr-x86.awk: Instruction attribute table generator
> +# Written by Masami Hiramatsu <mhiramat@xxxxxxxxxx>
> +#
> +# Usage: awk -f gen-insn-attr-x86.awk x86-opcode-map.txt > inat-tables.c
> +
> +# Awk implementation sanity check
> +function check_awk_implement() {
> +     if (sprintf("%x", 0) != "0")
> +             return "Your awk has a printf-format problem."
> +     return ""
> +}
> +
> +# Clear working vars
> +function clear_vars() {
> +     delete table
> +     delete lptable2
> +     delete lptable1
> +     delete lptable3
> +     eid = -1 # escape id
> +     gid = -1 # group id
> +     aid = -1 # AVX id
> +     tname = ""
> +}
> +
> +BEGIN {
> +     # Implementation error checking
> +     awkchecked = check_awk_implement()
> +     if (awkchecked != "") {
> +             print "Error: " awkchecked > "/dev/stderr"
> +             print "Please try to use gawk." > "/dev/stderr"
> +             exit 1
> +     }
> +
> +     # Setup generating tables
> +     print "/* x86 opcode map generated from x86-opcode-map.txt */"
> +     print "/* Do not change this code. */\n"
> +     ggid = 1
> +     geid = 1
> +     gaid = 0
> +     delete etable
> +     delete gtable
> +     delete atable
> +
> +     opnd_expr = "^[A-Za-z/]"
> +     ext_expr = "^\\("
> +     sep_expr = "^\\|$"
> +     group_expr = "^Grp[0-9A-Za-z]+"
> +
> +     imm_expr = "^[IJAOL][a-z]"
> +     imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
> +     imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
> +     imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
> +     imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
> +     imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
> +     imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
> +     imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
> +     imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
> +     imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
> +     imm_flag["Ob"] = "INAT_MOFFSET"
> +     imm_flag["Ov"] = "INAT_MOFFSET"
> +     imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
> +
> +     modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])"
> +     force64_expr = "\\([df]64\\)"
> +     rex_expr = "^REX(\\.[XRWB]+)*"
> +     fpu_expr = "^ESC" # TODO
> +
> +     lprefix1_expr = "\\((66|!F3)\\)"
> +     lprefix2_expr = "\\(F3\\)"
> +     lprefix3_expr = "\\((F2|!F3|66\\&F2)\\)"
> +     lprefix_expr = "\\((66|F2|F3)\\)"
> +     max_lprefix = 4
> +
> +     # All opcodes starting with lower-case 'v' or with (v1) superscript
> +     # accepts VEX prefix
> +     vexok_opcode_expr = "^v.*"
> +     vexok_expr = "\\(v1\\)"
> +     # All opcodes with (v) superscript supports *only* VEX prefix
> +     vexonly_expr = "\\(v\\)"
> +
> +     prefix_expr = "\\(Prefix\\)"
> +     prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
> +     prefix_num["REPNE"] = "INAT_PFX_REPNE"
> +     prefix_num["REP/REPE"] = "INAT_PFX_REPE"
> +     prefix_num["XACQUIRE"] = "INAT_PFX_REPNE"
> +     prefix_num["XRELEASE"] = "INAT_PFX_REPE"
> +     prefix_num["LOCK"] = "INAT_PFX_LOCK"
> +     prefix_num["SEG=CS"] = "INAT_PFX_CS"
> +     prefix_num["SEG=DS"] = "INAT_PFX_DS"
> +     prefix_num["SEG=ES"] = "INAT_PFX_ES"
> +     prefix_num["SEG=FS"] = "INAT_PFX_FS"
> +     prefix_num["SEG=GS"] = "INAT_PFX_GS"
> +     prefix_num["SEG=SS"] = "INAT_PFX_SS"
> +     prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
> +     prefix_num["VEX+1byte"] = "INAT_PFX_VEX2"
> +     prefix_num["VEX+2byte"] = "INAT_PFX_VEX3"
> +
> +     clear_vars()
> +}
> +
> +function semantic_error(msg) {
> +     print "Semantic error at " NR ": " msg > "/dev/stderr"
> +     exit 1
> +}
> +
> +function debug(msg) {
> +     print "DEBUG: " msg
> +}
> +
> +function array_size(arr,   i,c) {
> +     c = 0
> +     for (i in arr)
> +             c++
> +     return c
> +}
> +
> +/^Table:/ {
> +     print "/* " $0 " */"
> +     if (tname != "")
> +             semantic_error("Hit Table: before EndTable:.");
> +}
> +
> +/^Referrer:/ {
> +     if (NF != 1) {
> +             # escape opcode table
> +             ref = ""
> +             for (i = 2; i <= NF; i++)
> +                     ref = ref $i
> +             eid = escape[ref]
> +             tname = sprintf("inat_escape_table_%d", eid)
> +     }
> +}
> +
> +/^AVXcode:/ {
> +     if (NF != 1) {
> +             # AVX/escape opcode table
> +             aid = $2
> +             if (gaid <= aid)
> +                     gaid = aid + 1
> +             if (tname == "")        # AVX only opcode table
> +                     tname = sprintf("inat_avx_table_%d", $2)
> +     }
> +     if (aid == -1 && eid == -1)     # primary opcode table
> +             tname = "inat_primary_table"
> +}
> +
> +/^GrpTable:/ {
> +     print "/* " $0 " */"
> +     if (!($2 in group))
> +             semantic_error("No group: " $2 )
> +     gid = group[$2]
> +     tname = "inat_group_table_" gid
> +}
> +
> +function print_table(tbl,name,fmt,n)
> +{
> +     print "const insn_attr_t " name " = {"
> +     for (i = 0; i < n; i++) {
> +             id = sprintf(fmt, i)
> +             if (tbl[id])
> +                     print "    [" id "] = " tbl[id] ","
> +     }
> +     print "};"
> +}
> +
> +/^EndTable/ {
> +     if (gid != -1) {
> +             # print group tables
> +             if (array_size(table) != 0) {
> +                     print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
> +                                 "0x%x", 8)
> +                     gtable[gid,0] = tname
> +             }
> +             if (array_size(lptable1) != 0) {
> +                     print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
> +                                 "0x%x", 8)
> +                     gtable[gid,1] = tname "_1"
> +             }
> +             if (array_size(lptable2) != 0) {
> +                     print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
> +                                 "0x%x", 8)
> +                     gtable[gid,2] = tname "_2"
> +             }
> +             if (array_size(lptable3) != 0) {
> +                     print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
> +                                 "0x%x", 8)
> +                     gtable[gid,3] = tname "_3"
> +             }
> +     } else {
> +             # print primary/escaped tables
> +             if (array_size(table) != 0) {
> +                     print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
> +                                 "0x%02x", 256)
> +                     etable[eid,0] = tname
> +                     if (aid >= 0)
> +                             atable[aid,0] = tname
> +             }
> +             if (array_size(lptable1) != 0) {
> +                     print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
> +                                 "0x%02x", 256)
> +                     etable[eid,1] = tname "_1"
> +                     if (aid >= 0)
> +                             atable[aid,1] = tname "_1"
> +             }
> +             if (array_size(lptable2) != 0) {
> +                     print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
> +                                 "0x%02x", 256)
> +                     etable[eid,2] = tname "_2"
> +                     if (aid >= 0)
> +                             atable[aid,2] = tname "_2"
> +             }
> +             if (array_size(lptable3) != 0) {
> +                     print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
> +                                 "0x%02x", 256)
> +                     etable[eid,3] = tname "_3"
> +                     if (aid >= 0)
> +                             atable[aid,3] = tname "_3"
> +             }
> +     }
> +     print ""
> +     clear_vars()
> +}
> +
> +function add_flags(old,new) {
> +     if (old && new)
> +             return old " | " new
> +     else if (old)
> +             return old
> +     else
> +             return new
> +}
> +
> +# convert operands to flags.
> +function convert_operands(count,opnd,       i,j,imm,mod)
> +{
> +     imm = null
> +     mod = null
> +     for (j = 1; j <= count; j++) {
> +             i = opnd[j]
> +             if (match(i, imm_expr) == 1) {
> +                     if (!imm_flag[i])
> +                             semantic_error("Unknown imm opnd: " i)
> +                     if (imm) {
> +                             if (i != "Ib")
> +                                     semantic_error("Second IMM error")
> +                             imm = add_flags(imm, "INAT_SCNDIMM")
> +                     } else
> +                             imm = imm_flag[i]
> +             } else if (match(i, modrm_expr))
> +                     mod = "INAT_MODRM"
> +     }
> +     return add_flags(imm, mod)
> +}
> +
> +/^[0-9a-f]+\:/ {
> +     if (NR == 1)
> +             next
> +     # get index
> +     idx = "0x" substr($1, 1, index($1,":") - 1)
> +     if (idx in table)
> +             semantic_error("Redefine " idx " in " tname)
> +
> +     # check if escaped opcode
> +     if ("escape" == $2) {
> +             if ($3 != "#")
> +                     semantic_error("No escaped name")
> +             ref = ""
> +             for (i = 4; i <= NF; i++)
> +                     ref = ref $i
> +             if (ref in escape)
> +                     semantic_error("Redefine escape (" ref ")")
> +             escape[ref] = geid
> +             geid++
> +             table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
> +             next
> +     }
> +
> +     variant = null
> +     # converts
> +     i = 2
> +     while (i <= NF) {
> +             opcode = $(i++)
> +             delete opnds
> +             ext = null
> +             flags = null
> +             opnd = null
> +             # parse one opcode
> +             if (match($i, opnd_expr)) {
> +                     opnd = $i
> +                     count = split($(i++), opnds, ",")
> +                     flags = convert_operands(count, opnds)
> +             }
> +             if (match($i, ext_expr))
> +                     ext = $(i++)
> +             if (match($i, sep_expr))
> +                     i++
> +             else if (i < NF)
> +                     semantic_error($i " is not a separator")
> +
> +             # check if group opcode
> +             if (match(opcode, group_expr)) {
> +                     if (!(opcode in group)) {
> +                             group[opcode] = ggid
> +                             ggid++
> +                     }
> +                     flags = add_flags(flags, "INAT_MAKE_GROUP(" 
> group[opcode] ")")
> +             }
> +             # check force(or default) 64bit
> +             if (match(ext, force64_expr))
> +                     flags = add_flags(flags, "INAT_FORCE64")
> +
> +             # check REX prefix
> +             if (match(opcode, rex_expr))
> +                     flags = add_flags(flags, 
> "INAT_MAKE_PREFIX(INAT_PFX_REX)")
> +
> +             # check coprocessor escape : TODO
> +             if (match(opcode, fpu_expr))
> +                     flags = add_flags(flags, "INAT_MODRM")
> +
> +             # check VEX codes
> +             if (match(ext, vexonly_expr))
> +                     flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY")
> +             else if (match(ext, vexok_expr) || match(opcode, 
> vexok_opcode_expr))
> +                     flags = add_flags(flags, "INAT_VEXOK")
> +
> +             # check prefixes
> +             if (match(ext, prefix_expr)) {
> +                     if (!prefix_num[opcode])
> +                             semantic_error("Unknown prefix: " opcode)
> +                     flags = add_flags(flags, "INAT_MAKE_PREFIX(" 
> prefix_num[opcode] ")")
> +             }
> +             if (length(flags) == 0)
> +                     continue
> +             # check if last prefix
> +             if (match(ext, lprefix1_expr)) {
> +                     lptable1[idx] = add_flags(lptable1[idx],flags)
> +                     variant = "INAT_VARIANT"
> +             }
> +             if (match(ext, lprefix2_expr)) {
> +                     lptable2[idx] = add_flags(lptable2[idx],flags)
> +                     variant = "INAT_VARIANT"
> +             }
> +             if (match(ext, lprefix3_expr)) {
> +                     lptable3[idx] = add_flags(lptable3[idx],flags)
> +                     variant = "INAT_VARIANT"
> +             }
> +             if (!match(ext, lprefix_expr)){
> +                     table[idx] = add_flags(table[idx],flags)
> +             }
> +     }
> +     if (variant)
> +             table[idx] = add_flags(table[idx],variant)
> +}
> +
> +END {
> +     if (awkchecked != "")
> +             exit 1
> +     # print escape opcode map's array
> +     print "/* Escape opcode map array */"
> +     print "static const insn_attr_t * const inat_escape_tables[INAT_ESC_MAX 
> + 1]" \
> +           "[INAT_LSTPFX_MAX + 1] = {"
> +     for (i = 0; i < geid; i++)
> +             for (j = 0; j < max_lprefix; j++)
> +                     if (etable[i,j])
> +                             print "    ["i"]["j"] = "etable[i,j]","
> +     print "};\n"
> +     # print group opcode map's array
> +     print "/* Group opcode map array */"
> +     print "static const insn_attr_t * const inat_group_tables[INAT_GRP_MAX 
> + 1]"\
> +           "[INAT_LSTPFX_MAX + 1] = {"
> +     for (i = 0; i < ggid; i++)
> +             for (j = 0; j < max_lprefix; j++)
> +                     if (gtable[i,j])
> +                             print "    ["i"]["j"] = "gtable[i,j]","
> +     print "};\n"
> +     # print AVX opcode map's array
> +     print "/* AVX opcode map array */"
> +     print "static const insn_attr_t * const inat_avx_tables[X86_VEX_M_MAX + 
> 1]"\
> +           "[INAT_LSTPFX_MAX + 1] = {"
> +     for (i = 0; i < gaid; i++)
> +             for (j = 0; j < max_lprefix; j++)
> +                     if (atable[i,j])
> +                             print "    ["i"]["j"] = "atable[i,j]","
> +     print "};"
> +}

-- 
Mihai DonÈu

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