#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <orc/orc.h>
#include <orc/orcinternal.h>
#include <orc/orcx86.h>
#include <orc/orcx86-private.h>
#include <orc/orcx86insn.h>
#include <orc/orcsseinsn.h>
#include <orc/orcavx.h>
#include <orc/orcavxinsn.h>
#include <orc/orcavx-internal.h>

#define ORC_AVX_INSN_VALIDATE_OPERAND_12(op, n, reg)                           \
  if ((op->avx_operands & ORC_AVX_INSN_OPERAND_OP##n##_YMM) &&                 \
      orc_avx_insn_validate_reg (reg)) {                                       \
    return TRUE;                                                               \
  } else if ((op->avx_operands & ORC_SSE_INSN_OPERAND_OP##n##_XMM) &&          \
      orc_avx_insn_validate_sse_reg (reg)) {                                   \
    return TRUE;                                                               \
  } else {                                                                     \
    ORC_ERROR ("Unsupported operand %d with reg %d for op %s", n, reg,         \
        op->name);                                                             \
    return FALSE;                                                              \
  }

#define ORC_AVX_INSN_VALIDATE_OPERAND_34(op, n, reg)                           \
  if ((op->avx_operands & ORC_AVX_INSN_OPERAND_OP##n##_YMM) &&                 \
      orc_avx_insn_validate_reg (reg)) {                                       \
    return TRUE;                                                               \
  } else if ((op->avx_operands & ORC_AVX_INSN_OPERAND_OP##n##_XMM) &&          \
      orc_avx_insn_validate_sse_reg (reg)) {                                   \
    return TRUE;                                                               \
  } else {                                                                     \
    ORC_ERROR ("Unsupported operand %d with reg %d for op %s", n, reg,         \
        op->name);                                                             \
    return FALSE;                                                              \
  }

typedef struct _OrcAVXInsnOp {
  char name[16];
  unsigned int target_flags;
  unsigned int operands;
  unsigned int avx_operands;
  OrcX86InsnOpcodePrefix prefix;
  OrcX86InsnOpcodeEscapeSequence escape;
  orc_uint32 opcode;
  orc_uint8 extension;
  orc_uint32 flags;
} OrcAVXInsnOp;

/* clang-format off */
static const OrcAVXInsnOp orc_avx_ops[] = {
  { "vperm2f128"  , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM_IMM8      , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x06},
  { "vblendpd"    , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM_IMM8      , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x0d},
  { "vextractf128", 0, ORC_AVX_INSN_TYPE_SSEM_AVX_IMM8          , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x19},
  { "vperm2i128"  , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM_IMM8      , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x46},
  { "vblendvpd"   , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM_AVX       , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x4b},
  { "vblendvpd"   , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM_SSE       , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x4b},
  { "vsqrtps"     , 0, ORC_AVX_INSN_TYPE_AVX_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x51 },
  { "vsqrtps"     , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x51 },
  { "vandps"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x54 },
  { "vandps"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x54 },
  /* 10 */
  { "vorps"       , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x56 },
  { "vorps"       , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x56 },
  { "vaddps"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x58 },
  { "vaddps"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x58 },
  { "vmulps"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x59 },
  { "vmulps"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x59 },
  { "vsubps"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5c },
  { "vsubps"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5c },
  { "vminps"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5d },
  { "vminps"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5d },
  /* 20 */
  { "vdivps"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5e },
  { "vdivps"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5e },
  { "vmaxps"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5f },
  { "vmaxps"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5f },
  { "vldmxcsr"     , 0, ORC_X86_INSN_TYPE_MEM32                  , 0, ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xae, 2 },
  { "vstmxcsr"     , 0, ORC_X86_INSN_TYPE_MEM32                  , 0, ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xae, 3 },
  { "vsqrtpd"     , 0, ORC_AVX_INSN_TYPE_AVX_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x51 },
  { "vsqrtpd"     , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x51 },
  { "vaddpd"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x58 },
  { "vaddpd"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x58 },
  /* 30 */
  { "vmulpd"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x59 },
  { "vmulpd"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x59 },
  { "vcvtps2pd"   , 0, ORC_AVX_INSN_TYPE_AVX_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5a },
  { "vcvtps2pd"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5a },
  { "vcvtpd2ps"   , 0, ORC_AVX_INSN_TYPE_SSE_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5a },
  { "vcvtpd2ps"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5a },
  { "vcvtdq2ps"   , 0, ORC_AVX_INSN_TYPE_AVX_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5b },
  { "vcvtdq2ps"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5b },
  { "vcvttps2dq"  , 0, ORC_AVX_INSN_TYPE_AVX_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5b },
  { "vcvttps2dq"  , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5b },
  /* 40 */
  { "vsubpd"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5c },
  { "vsubpd"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5c },
  { "vminpd"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5d },
  { "vminpd"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5d },
  { "vdivpd"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5e },
  { "vdivpd"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5e },
  { "vmaxpd"      , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5f },
  { "vmaxpd"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x5f },
  { "vcmpeqpd"    , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 0 },
  { "vcmpeqpd"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 0 },
  /* 50 */
  { "vcmpltpd"    , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 1 },
  { "vcmpltpd"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 1 },
  { "vcmplepd"    , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 2 },
  { "vcmplepd"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 2 },
  { "vcmpeqps"    , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 0 },
  { "vcmpeqps"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 0 },
  { "vcmpltps"    , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 1 },
  { "vcmpltps"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 1 },
  { "vcmpleps"    , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 2 },
  { "vcmpleps"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc2, 2 },
  /* 60 */
  { "vcvtdq2pd"   , 0, ORC_AVX_INSN_TYPE_AVX_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe6 },
  { "vcvtdq2pd"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe6 },
  { "vcvttpd2dq"  , 0, ORC_AVX_INSN_TYPE_AVX_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe6 },
  { "vcvttpd2dq"  , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe6 },
  { "vpunpcklbw"  , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x60 },
  { "vpunpcklwd"  , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x61 },
  { "vpunpckldq"  , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x62 },
  { "vpacksswb"   , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x63 },
  { "vpcmpgtb"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x64 },
  { "vpcmpgtw"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x65 },
  /* 70 */
  { "vpcmpgtd"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x66 },
  { "vpackuswb"   , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x67 },
  { "vpunpckhbw"  , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x68 },
  { "vpunpckhwd"  , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x69 },
  { "vpunpckhdq"  , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6a },
  { "vpackssdw"   , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6b },
  { "vmovd"       , 0, ORC_SSE_INSN_TYPE_SSE_REGM32             , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6e },
  { "vmovq"       , 0, ORC_SSE_INSN_TYPE_SSE_REGM64             , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6e }, // load
  { "vpsrlw"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_IMM8           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x71, 2 },
  { "vpsraw"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_IMM8           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x71, 4 },
  /* 80 */
  { "vpsllw"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_IMM8           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x71, 6 },
  { "vpsrld"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_IMM8           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x72, 2 },
  { "vpsrad"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_IMM8           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x72, 4 },
  { "vpslld"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_IMM8           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x72, 6 },
  { "vpsrlq"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_IMM8           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x73, 2 },
  { "vpsllq"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_IMM8           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x73, 6 },
  { "vpcmpeqb"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x74 },
  { "vpcmpeqw"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x75 },
  { "vpcmpeqd"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x76 },
  { "vzeroupper"  , 0, ORC_X86_INSN_OPERAND_NONE, 0             , ORC_X86_INSN_OPCODE_PREFIX_NONE, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x77 },
  /* 90 */
  { "vmovd"       , 0, ORC_SSE_INSN_TYPE_REGM32_SSE             , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x7e },
  { "vmovq"       , 0, ORC_SSE_INSN_TYPE_REGM64_SSE             , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x7e }, // store
  { "vmovq"       , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x7e },
  { "vpinsrw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_REG32M16_IMM8  , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc4 },
  { "vpextrw"     , 0, ORC_SSE_INSN_TYPE_REG32TO64_SSE_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xc5 },
  { "vpsrlw"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd1 },
  { "vpsrld"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd2 },
  { "vpsrlq"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd3 },
  { "vpaddq"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd4 },
  { "vpmullw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd5 },
  /* 100 */
  { "vmovq"       , 0, ORC_SSE_INSN_TYPE_SSEM_SSE               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd6 },
  { "vpsubusb"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd8 },
  { "vpsubusw"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd9 },
  { "vpminub"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xda },
  { "vpand"       , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xdb },
  { "vpaddusb"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xdc },
  { "vpaddusw"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xdd },
  { "vpmaxub"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xde },
  { "vpandn"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xdf },
  { "vpavgb"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe0 },
  /* 110 */
  { "vpsraw"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe1 },
  { "vpsrad"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe2 },
  { "vpavgw"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe3 },
  { "vpmulhuw"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe4 },
  { "vpmulhw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe5 },
  { "vpsubsb"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe8 },
  { "vpsubsw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe9 },
  { "vpminsw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xea },
  { "vpor"        , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xeb },
  { "vpaddsb"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xec },
  /* 120 */
  { "vpaddsw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xed },
  { "vpmaxsw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xee },
  { "vpxor"       , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xef },
  { "vpsllw"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf1 },
  { "vpslld"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf2 },
  { "vpsllq"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf3 },
  { "vpmuludq"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf4 },
  { "vpsadbw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf6 },
  { "vpsubb"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf8 },
  { "vpsubw"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf9 },
  /* 130 */
  { "vpsubd"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfa },
  { "vpsubq"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfb },
  { "vpaddb"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfc },
  { "vpaddw"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfd },
  { "vpaddd"      , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfe },
  { "vpunpcklqdq" , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6c },
  { "vmovdqa"     , 0, ORC_AVX_INSN_TYPE_AVX_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6f },
  { "vmovdqa"     , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6f },
  { "vpshufd"     , 0, ORC_SSE_INSN_TYPE_SSE_SSEM_IMM8          , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x70 },
  { "vmovdqa"     , 0, ORC_AVX_INSN_TYPE_AVXM_AVX               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x7f },
  /* 140 */
  { "vmovdqa"     , 0, ORC_SSE_INSN_TYPE_SSEM_SSE               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x7f },
  { "vpslldq"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_IMM8           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x73, 7 },
  { "vmovntdq"    , 0, ORC_AVX_INSN_TYPE_MEM_AVX               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe7 },
  { "vmovntdq"    , 0, ORC_SSE_INSN_TYPE_MEM_SSE               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe7 },
  { "vpshuflw"    , 0, ORC_SSE_INSN_TYPE_SSE_SSEM_IMM8          , ORC_X86_INSN_OPCODE_PREFIX_0XF2, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x70 },
  { "vmovdqu"     , 0, ORC_AVX_INSN_TYPE_AVX_AVXM               , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6f },
  { "vmovdqu"     , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6f },
  { "vmovdqu"     , 0, ORC_AVX_INSN_TYPE_AVXM_AVX               , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x7f },
  { "vmovdqu"     , 0, ORC_SSE_INSN_TYPE_SSEM_SSE               , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x7f },
  { "vpshufhw"    , 0, ORC_SSE_INSN_TYPE_SSE_SSEM_IMM8          , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x70 },
  /* 150 */
  { "vpshufb"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x00 },
  { "vpsignb"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x08 },
  { "vpsignw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x09 },
  { "vpsignd"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x0a },
  { "vpabsb"      , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x1c },
  { "vpabsw"      , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x1d },
  { "vpabsd"      , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x1e },
  { "vpextrb"     , 0, ORC_SSE_INSN_TYPE_REG32TO64M8_SSE_IMM8   , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x14 },
  { "vpextrw"     , 0, ORC_SSE_INSN_TYPE_REG32TO64M16_SSE_IMM8  , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x15 },
  { "vpinsrb"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_REG32M8_IMM8   , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x20 },
  /* 160 */
  { "vpmovsxbw"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x20 },
  { "vpinsrd"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_REG32TO64M32_IMM8, ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x22 },
  { "vpmovsxwd"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x23 },
  { "vpmovsxdq"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x25 },
  { "vpmuldq"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x28 },
  { "vpcmpeqq"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x29 },
  { "vpackusdw"   , 0, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x2b },
  { "vpackusdw"   , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x2b },
  { "vpmovzxbw"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x30 },
  { "vpmovzxwd"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x33 },
  /* 170 */
  { "vpmovzxdq"   , 0, ORC_SSE_INSN_TYPE_SSE_SSEM               , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x35 },
  { "vpminsb"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x38 },
  { "vpminsd"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x39 },
  { "vpminuw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3A },
  { "vpminud"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3B },
  { "vpmaxsb"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3C },
  { "vpmaxsd"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3D },
  { "vpmaxuw"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3E },
  { "vpmaxud"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3F },
  { "vpmulld"     , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x40 },
  /* 180 */
  { "vpcmpgtq"    , 0, ORC_AVX_INSN_TYPE_SSE_SSE_SSEM           , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x37 },
  /* AVX2 */
  { "vpermq"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVXM_IMM8    , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x00, 0, ORC_X86_INSN_OPCODE_FLAG_VEX_W1},
  { "vpblendd"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM_IMM8, ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F3A, 0x02},
  { "vpbroadcastd", ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x58},
  { "vpbroadcastq", ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x59},
  { "vpbroadcastb", ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x78},
  { "vpbroadcastw", ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x79},
  { "vpunpcklbw"  , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x60 },
  { "vpunpcklwd"  , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x61 },
  { "vpunpckldq"  , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x62 },
  /* 190 */
  { "vpacksswb"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x63 },
  { "vpcmpgtb"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x64 },
  { "vpcmpgtw"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x65 },
  { "vpcmpgtd"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x66 },
  { "vpackuswb"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x67 },
  { "vpunpckhbw"  , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x68 },
  { "vpunpckhwd"  , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x69 },
  { "vpunpckhdq"  , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6a },
  { "vpackssdw"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6b },
  { "vpsrlw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x71, 2 },
  /* 200 */
  { "vpsraw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x71, 4 },
  { "vpsllw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x71, 6 },
  { "vpsrld"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x72, 2 },
  { "vpsrad"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x72, 4 },
  { "vpslld"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x72, 6 },
  { "vpsrlq"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x73, 2 },
  { "vpsllq"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x73, 6 },
  { "vpcmpeqb"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x74 },
  { "vpcmpeqw"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x75 },
  { "vpcmpeqd"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x76 },
  /* 210 */
  { "vpsrlw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_SSEM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd1 },
  { "vpsrld"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_SSEM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd2 },
  { "vpsrlq"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_SSEM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd3 },
  { "vpaddq"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd4 },
  { "vpmullw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd5 },
  { "vpsubusb"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd8 },
  { "vpsubusw"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xd9 },
  { "vpminub"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xda },
  { "vpand"       , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xdb },
  { "vpaddusb"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xdc },
  /* 220 */
  { "vpaddusw"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xdd },
  { "vpmaxub"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xde },
  { "vpandn"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xdf },
  { "vpavgb"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe0 },
  { "vpsraw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_SSEM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe1 },
  { "vpsrad"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_SSEM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe2 },
  { "vpavgw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe3 },
  { "vpmulhuw"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe4 },
  { "vpmulhw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe5 },
  { "vpsubsb"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe8 },
  /* 230 */
  { "vpsubsw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xe9 },
  { "vpminsw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xea },
  { "vpor"        , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xeb },
  { "vpaddsb"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xec },
  { "vpaddsw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xed },
  { "vpmaxsw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xee },
  { "vpxor"       , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xef },
  { "vpsllw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_SSEM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf1 },
  { "vpslld"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_SSEM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf2 },
  { "vpsllq"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_SSEM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf3 },
  /* 240 */
  { "vpmuludq"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf4 },
  { "vpmaddwd"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf5 },
  { "vpsadbw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf6 },
  { "vpsubb"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf8 },
  { "vpsubw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xf9 },
  { "vpsubd"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfa },
  { "vpsubq"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfb },
  { "vpaddb"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfc },
  { "vpaddw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfd },
  { "vpaddd"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0xfe },
  /* 250 */
  { "vpunpcklqdq" , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6c },
  { "vpunpckhqdq" , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x6d },
  { "vpshufd"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVXM_IMM8    , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x70 },
  { "vpsrldq"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x73, 3 },
  { "vpslldq"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_IMM8     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x73, 7 },
  { "vpshuflw"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVXM_IMM8    , ORC_X86_INSN_OPCODE_PREFIX_0XF2, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x70 },
  { "vpshufhw"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVXM_IMM8    , ORC_X86_INSN_OPCODE_PREFIX_0XF3, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F, 0x70 },
  { "vpshufb"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x00 },
  { "vpsignb"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x08 },
  { "vpsignw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x09 },
  /* 260 */
  { "vpsignd"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x0a },
  { "vpabsb"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVXM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x1c },
  { "vpabsw"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVXM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x1d },
  { "vpabsd"      , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVXM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x1e },
  { "vpmovsxbw"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x20 },
  { "vpmovsxbd"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x21 },
  { "vpmovsxbq"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x22 },
  { "vpmovsxwd"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x23 },
  { "vpmovsxwq"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x24 },
  { "vpmovsxdq"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x25 },
  /* 270 */
  { "vpmuldq"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x28 },
  { "vpcmpeqq"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x29 },
  { "vpmovzxbw"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x30 },
  { "vpmovzxbd"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x31 },
  { "vpmovzxbq"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x32 },
  { "vpmovzxwd"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x33 },
  { "vpmovzxwq"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x34 },
  { "vpmovzxdq"   , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_SSEM         , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x35 },
  { "vpminsb"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x38 },
  { "vpminsd"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x39 },
  /* 280 */
  { "vpminuw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3A },
  { "vpminud"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3B },
  { "vpmaxsb"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3C },
  { "vpmaxsd"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3D },
  { "vpmaxuw"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3E },
  { "vpmaxud"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x3F },
  { "vpmulld"     , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x40 },
  { "vpcmpgtq"    , ORC_TARGET_AVX_AVX2, ORC_AVX_INSN_TYPE_AVX_AVX_AVXM     , ORC_X86_INSN_OPCODE_PREFIX_0X66, ORC_X86_INSN_OPCODE_ESCAPE_SEQUENCE_0X0F38, 0x37 },
};
/* clang-format on */

void
orc_x86_emit_mov_memoffset_avx (OrcCompiler *compiler, int size, int offset,
    int reg1, int reg2, int is_aligned)
{
  switch (size) {
    // AVX does not provide loads except vmov(u*, dq*, ap*)
    case 1:
      orc_avx_emit_pxor (compiler, reg2, reg2, reg2);
      orc_avx_sse_emit_pinsrb_memoffset (compiler, 0, offset,
          ORC_AVX_SSE_REG (reg2), reg1,
          ORC_AVX_SSE_REG (reg2));
      break;
    case 2:
      orc_avx_emit_pxor (compiler, reg2, reg2, reg2);
      orc_avx_sse_emit_pinsrw_memoffset (compiler, 0, offset,
          ORC_AVX_SSE_REG (reg2), reg1,
          ORC_AVX_SSE_REG (reg2));
      break;
    case 4:
      orc_avx_sse_emit_movd_load_memoffset (compiler, offset,
          reg1, ORC_AVX_SSE_REG (reg2));
      break;
    case 8:
      orc_avx_sse_emit_movq_load_memoffset (compiler, offset,
          reg1, ORC_AVX_SSE_REG (reg2));
      break;
    case 16:
      if (is_aligned) {
        orc_avx_sse_emit_movdqa_load_memoffset (compiler, offset,
            reg1, ORC_AVX_SSE_REG (reg2));
      } else {
        orc_avx_sse_emit_movdqu_load_memoffset (compiler, offset,
            reg1, ORC_AVX_SSE_REG (reg2));
      }
      break;
    case 32:
      if (is_aligned) {
        orc_avx_emit_movdqa_load_memoffset (compiler, offset, reg1, reg2);
      } else {
        orc_avx_emit_movdqu_load_memoffset (compiler, offset, reg1, reg2);
      }
      break;
    default:
      ORC_COMPILER_ERROR (compiler, "bad load size %d", size);
      break;
  }
}

void
orc_x86_emit_mov_memindex_avx (OrcCompiler *compiler, int size, int offset,
    int reg1, int regindex, int shift, int reg2, int is_aligned)
{
  switch (size) {
    // VEX instructions zeroupper the high lane
    case 4:
      orc_avx_sse_emit_movd_load_memindex (compiler, offset,
          ORC_AVX_SSE_REG (reg1), regindex, shift, ORC_AVX_SSE_REG (reg2));
      break;
    case 8:
      orc_avx_sse_emit_movq_load_memindex (compiler, offset,
          ORC_AVX_SSE_REG (reg1), regindex, shift, ORC_AVX_SSE_REG (reg2));
      break;
    case 16:
      if (is_aligned) {
        orc_avx_sse_emit_movdqa_load_memindex (compiler, offset,
            ORC_AVX_SSE_REG (reg1), regindex, shift, ORC_AVX_SSE_REG (reg2));
      } else {
        orc_avx_sse_emit_movdqu_load_memindex (compiler, offset,
            ORC_AVX_SSE_REG (reg1), regindex, shift, ORC_AVX_SSE_REG (reg2));
      }
      break;
    case 32:
      if (is_aligned) {
        orc_avx_emit_movdqa_load_memindex (compiler, offset, reg1, regindex,
            shift, reg2);
      } else {
        orc_avx_emit_movdqu_load_memindex (compiler, offset, reg1, regindex,
            shift, reg2);
      }
      break;
    default:
      ORC_COMPILER_ERROR (compiler, "bad load size %d", size);
      break;
  }
}

void
orc_x86_emit_mov_avx_memoffset (OrcCompiler *compiler, int size, int reg1,
    int offset, int reg2, int aligned, int uncached)
{
  switch (size) {
    case 1:
      orc_avx_sse_emit_pextrb_memoffset (compiler, 0, offset,
          ORC_AVX_SSE_REG (reg1), reg2);
      break;
    case 2:
      orc_avx_sse_emit_pextrw_memoffset (compiler, 0, offset,
          ORC_AVX_SSE_REG (reg1), reg2);
      break;
    case 4:
      orc_avx_sse_emit_movd_store_memoffset (compiler, offset,
          ORC_AVX_SSE_REG (reg1), reg2);
      break;
    case 8:
      orc_avx_sse_emit_movq_store_memoffset (compiler, offset,
          ORC_AVX_SSE_REG (reg1), reg2);
      break;
    case 16:
      if (aligned) {
        if (uncached) {
          orc_avx_sse_emit_movntdq_store_memoffset (compiler, offset,
              ORC_AVX_SSE_REG (reg1), reg2);
        } else {
          orc_avx_sse_emit_movdqa_store_memoffset (compiler, offset,
              ORC_AVX_SSE_REG (reg1), reg2);
        }
      } else {
        orc_avx_sse_emit_movdqu_store_memoffset (compiler, offset,
            ORC_AVX_SSE_REG (reg1), reg2);
      }
      break;
    case 32:
      if (aligned) {
        if (uncached) {
          orc_avx_emit_movntdq_store_memoffset (compiler, offset, reg1, reg2);
        } else {
          orc_avx_emit_movdqa_store_memoffset (compiler, offset, reg1, reg2);
        }
      } else {
        orc_avx_emit_movdqu_store_memoffset (compiler, offset, reg1, reg2);
      }
      break;
    default:
      ORC_COMPILER_ERROR (compiler, "bad store size %d", size);
      break;
  }
}

/* The pbroadcast[b,w,d,q] support a destination register of AVX or SSE,
 * Here, it is assumed that the destination register is always an AVX one
 */
void
orc_avx_emit_broadcast (OrcCompiler *const compiler, const int s1, const int d,
    const int size)
{
  switch (size) {
    case 1:
      orc_avx_emit_pbroadcastb (compiler, ORC_AVX_SSE_REG (s1), d);
      break;
    case 2:
      orc_avx_emit_pbroadcastw (compiler, ORC_AVX_SSE_REG (s1), d);
      break;
    case 4:
      orc_avx_emit_pbroadcastd (compiler, ORC_AVX_SSE_REG (s1), d);
      break;
    case 8:
      orc_avx_emit_pbroadcastq (compiler, ORC_AVX_SSE_REG (s1), d);
      break;
    case 16:
      orc_avx_emit_permute2i128 (compiler, ORC_AVX_PERMUTE (0, 0), s1, s1, d);
      break;
    default:
      ORC_COMPILER_ERROR (compiler, "this variable size cannot be broadcast");
      break;
  }
}

void
orc_avx_set_mxcsr (OrcCompiler *compiler)
{
  orc_vex_emit_cpuinsn_store_memoffset (compiler, ORC_AVX_stmxcsr, 0,
      (int)ORC_STRUCT_OFFSET (OrcExecutor, params[ORC_VAR_A4]),
      0, compiler->exec_reg);

  orc_x86_emit_mov_memoffset_reg (compiler, 4,
      (int)ORC_STRUCT_OFFSET (OrcExecutor, params[ORC_VAR_A4]),
      compiler->exec_reg, compiler->gp_tmpreg);

  orc_x86_emit_mov_reg_memoffset (compiler, 4, compiler->gp_tmpreg,
      (int)ORC_STRUCT_OFFSET (OrcExecutor, params[ORC_VAR_C1]),
      compiler->exec_reg);

  orc_x86_emit_cpuinsn_imm_reg (compiler, ORC_X86_or_imm32_rm, 4, 0x8040,
      compiler->gp_tmpreg);

  orc_x86_emit_mov_reg_memoffset (compiler, 4, compiler->gp_tmpreg,
      (int)ORC_STRUCT_OFFSET (OrcExecutor, params[ORC_VAR_A4]),
      compiler->exec_reg);

  orc_vex_emit_cpuinsn_store_memoffset (compiler, ORC_AVX_ldmxcsr, 0,
      (int)ORC_STRUCT_OFFSET (OrcExecutor, params[ORC_VAR_A4]),
      0, compiler->exec_reg);
}

void
orc_avx_restore_mxcsr (OrcCompiler *compiler)
{
  orc_vex_emit_cpuinsn_store_memoffset (compiler, ORC_AVX_ldmxcsr, 0,
      (int)ORC_STRUCT_OFFSET (OrcExecutor, params[ORC_VAR_A4]),
      0, compiler->exec_reg);
}

static orc_bool
orc_avx_insn_validate_reg (int reg)
{
  if (reg >= X86_YMM0 && reg < X86_YMM0 + 16)
    return TRUE;
  else
    return FALSE;
}

static orc_bool
orc_avx_insn_validate_sse_reg (int reg)
{
  if (reg >= X86_XMM0 && reg < X86_XMM0 + 16)
    return TRUE;
  else
    return FALSE;
}

static void
orc_avx_insn_from_opcode (OrcX86Insn *insn, int index, const OrcAVXInsnOp *op)
{
  insn->name = op->name;
  insn->opcode = op->opcode;
  insn->opcode_type = ORC_X86_INSN_OPCODE_TYPE_OTHER;
  insn->opcode_escape = op->escape;
  insn->opcode_prefix = op->prefix;
  insn->opcode_flags = op->flags;
  /* If the operands require a YMM register, use the VEX256 prefix,
   * VEX128 otherwise
   */
  insn->prefix = ORC_X86_INSN_PREFIX_VEX128;
  if (op->avx_operands & (ORC_AVX_INSN_OPERAND_OP1_YMM |
      ORC_AVX_INSN_OPERAND_OP2_YMM | ORC_AVX_INSN_OPERAND_OP3_YMM |
      ORC_AVX_INSN_OPERAND_OP4_YMM))
    insn->prefix = ORC_X86_INSN_PREFIX_VEX256;
  insn->extension = op->extension;
  if (!orc_x86_insn_encoding_from_operands (&insn->encoding, op->operands,
      op->extension, FALSE)) {
    ORC_ERROR ("Can not encode %s (%d) opcode", op->name, index);
  }
}

static orc_bool
orc_avx_insn_validate_operand (OrcX86InsnOperandNum n, int reg, void *data)
{
  OrcAVXInsnOp *op = (OrcAVXInsnOp *)data;
  switch (n) {
    case ORC_X86_INSN_OPERAND_NUM_1:
      ORC_AVX_INSN_VALIDATE_OPERAND_12 (op, 1, reg)
      break;
    case ORC_X86_INSN_OPERAND_NUM_2:
      ORC_AVX_INSN_VALIDATE_OPERAND_12 (op, 2, reg)
      break;
    case ORC_X86_INSN_OPERAND_NUM_3:
      ORC_AVX_INSN_VALIDATE_OPERAND_34 (op, 3, reg)
    case ORC_X86_INSN_OPERAND_NUM_4:
      ORC_AVX_INSN_VALIDATE_OPERAND_34 (op, 4, reg)
    default:
      ORC_ERROR ("Unsupported operand num %d", n);
      return FALSE;
  }
  return TRUE;
}

static orc_bool
orc_avx_insn_validate_operands (OrcCompiler *c, int index,
    OrcX86InsnOperandSize size, const int dest, const int src0, const int src1,
    const int src2, orc_int64 imm)
{
  const OrcAVXInsnOp *op = orc_avx_ops + index;

  if (!orc_x86_insn_validate_operands (c, op->operands, size, dest, src0, src1,
    src2, imm, &orc_avx_insn_validate_operand, (void *)op)) {
    ORC_ERROR ("Failed validating %s (%d)", op->name, index);
    return FALSE;
  }

  return TRUE;
}

void
orc_vex_emit_cpuinsn_none (OrcCompiler *p, const int index)
{
  OrcX86Insn *xinsn;
  const OrcAVXInsnOp *op = orc_avx_ops + index;

  if (!orc_x86_insn_validate_no_operands (op->operands)) {
    ORC_ERROR ("Calling the opcode %d with parameters", index);
    return;
  }

  xinsn = orc_x86_get_output_insn (p);
  orc_avx_insn_from_opcode (xinsn, index, op);
}

void
orc_vex_emit_cpuinsn_avx (OrcCompiler *const p, const int index,
    const int src0, const int src1, const int src2, const int dest)
{
  OrcX86Insn *xinsn;
  const OrcAVXInsnOp *op = orc_avx_ops + index;

  /* checks */
  if (!orc_avx_insn_validate_operands (p, index,
      ORC_X86_INSN_OPERAND_SIZE_NONE, dest, src0, src1, src2, 0))
    return;

  xinsn = orc_x86_get_output_insn (p);
  orc_avx_insn_from_opcode (xinsn, index, op);
  orc_x86_insn_set_operands (xinsn, op->operands,
      ORC_X86_INSN_OPERAND_SIZE_NONE, dest, src0, src1, src2);
  /* Special case for cmpeqpd until cmpleps, all are REG_REG_REGM_IMM8 but faked on
   * the definition
   */
  if (index >= ORC_AVX_cmpeqpd && index <= ORC_AVX_SSE_cmpleps) {
    xinsn->encoding = ORC_X86_INSN_ENCODING_RVMI;
    orc_x86_insn_operand_set (&xinsn->operands[3],
        ORC_X86_INSN_OPERAND_TYPE_IMM, ORC_X86_INSN_OPERAND_SIZE_8, 0);
    xinsn->imm = op->extension;
    xinsn->extension = 0;
  }
}

/*
 * Used in
 * vmovd (SSE_REGM32)
 */
void
orc_vex_emit_cpuinsn_size (OrcCompiler *const p, const int index,
    const int size, const int src0, const int src1, const int src2,
    const int dest)
{
  OrcX86Insn *xinsn;
  OrcX86InsnOperandSize opsize = orc_x86_insn_size_to_operand_size (size);
  const OrcAVXInsnOp *op = orc_avx_ops + index;

  /* checks */
  if (!orc_avx_insn_validate_operands (p, index, size, dest, src0, src1,
      src2, 0))
    return;

  xinsn = orc_x86_get_output_insn (p);
  orc_avx_insn_from_opcode (xinsn, index, op);
  orc_x86_insn_set_operands (xinsn, op->operands, opsize, dest, src0, src1, src2);
}

/*
 * Used in
 * vpinsrw (SSE_SSE_REG32M16_IMM8)
 */
void
orc_vex_emit_cpuinsn_imm (OrcCompiler *const p, const int index, const int size,
    const int imm, const int src0, const int src1, const int dest)
{
  OrcX86Insn *xinsn;
  const OrcAVXInsnOp *op = orc_avx_ops + index;
  const OrcX86InsnOperandSize opsize = orc_x86_insn_size_to_operand_size (size);

  if (!orc_avx_insn_validate_operands (p, index, size, dest, src0, src1,
      ORC_REG_INVALID, 0))
    return;

  xinsn = orc_x86_get_output_insn (p);
  orc_avx_insn_from_opcode (xinsn, index, op);
  orc_x86_insn_set_operands (xinsn, op->operands, opsize, dest, src0, src1,
      ORC_REG_INVALID);
  orc_x86_insn_set_imm (xinsn, op->operands, ORC_X86_INSN_OPERAND_SIZE_8, imm);
}

/*
 * Used in
 * vpinsrb (SSE_SSE_REGM32_IMM8)
 * vpinsrd (SSE_SSE_REGM32TO64_IMM8)
 * vmovd (SSE_REGM32)
 * vpinsrw (SSE_SSE_REG32M16_IMM8)
 */
void
orc_vex_emit_cpuinsn_load_memoffset (OrcCompiler *const p, const int index,
    const int imm, const int offset, const int src0, const int src1,
    const int dest)
{
  OrcX86Insn *xinsn;
  const OrcAVXInsnOp *op = orc_avx_ops + index;
  const OrcX86InsnOperandSize size = p->is_64bit ? ORC_X86_INSN_OPERAND_SIZE_64 :
      ORC_X86_INSN_OPERAND_SIZE_32;

  /* checks */
  if (!orc_avx_insn_validate_operands (p, index, size, dest, src0, src1,
      ORC_REG_INVALID, 0))
    return;

  xinsn = orc_x86_get_output_insn (p);
  orc_avx_insn_from_opcode (xinsn, index, op);
  orc_x86_insn_set_operands (xinsn, op->operands,
      ORC_X86_INSN_OPERAND_SIZE_NONE, dest, src0, src1, ORC_REG_INVALID);
  orc_x86_insn_set_mem (xinsn, op->operands, size,
      ORC_X86_INSN_OPERAND_TYPE_OFF, dest, src0, src1, 
      ORC_REG_INVALID);
  orc_x86_insn_set_imm (xinsn, op->operands, ORC_X86_INSN_OPERAND_SIZE_8, imm);
  xinsn->offset = offset;
}

/*
 * Used in 
 * vmovd (REGM32_SSE)
 * vpextrw (REG32TO64_SSE_IMM8)
 * vpextrb (REGM32TO64_SSE_IMM8)
 * vpextrw (REGM32TO64_SSE_IMM8)
 */
void
orc_vex_emit_cpuinsn_store_memoffset (OrcCompiler *const p, const int index,
    const int imm, const int offset, const int src,
    const int dest)
{
  OrcX86Insn *xinsn;
  const OrcAVXInsnOp *op = orc_avx_ops + index;
  const OrcX86InsnOperandSize size = p->is_64bit ?
      ORC_X86_INSN_OPERAND_SIZE_64 : ORC_X86_INSN_OPERAND_SIZE_32;

  /* checks */
  if (!orc_avx_insn_validate_operands (p, index, size, dest, src,
      ORC_REG_INVALID, ORC_REG_INVALID, 0))
    return;

  xinsn = orc_x86_get_output_insn (p);
  orc_avx_insn_from_opcode (xinsn, index, op);
  orc_x86_insn_set_operands (xinsn, op->operands,
      ORC_X86_INSN_OPERAND_SIZE_NONE, dest, src, ORC_REG_INVALID,
      ORC_REG_INVALID);
  orc_x86_insn_set_mem (xinsn, op->operands, size,
      ORC_X86_INSN_OPERAND_TYPE_OFF, dest, src, ORC_REG_INVALID, 
      ORC_REG_INVALID);
  orc_x86_insn_set_imm (xinsn, op->operands, ORC_X86_INSN_OPERAND_SIZE_8, imm);
  xinsn->offset = offset;
}

/*
 * Used in
 * vpinsrb (SSE_SSE_REGM32_IMM8)
 * vpinsrd (SSE_SSE_REGM32TO64_IMM8)
 * vmovd (SSE_REGM32)
 * vpinsrw (SSE_SSE_REG32M16_IMM8)
 */
void
orc_vex_emit_cpuinsn_load_memindex (OrcCompiler *const p, const int index,
    const int imm, const int offset, const int src, const int src_index,
    const int shift, int dest)
{
  OrcX86Insn *xinsn;
  const OrcAVXInsnOp *op = orc_avx_ops + index;
  const OrcX86InsnOperandSize size = p->is_64bit ?
      ORC_X86_INSN_OPERAND_SIZE_64 : ORC_X86_INSN_OPERAND_SIZE_32;

  /* checks */
  if (!orc_avx_insn_validate_operands (p, index, size, dest, src,
      ORC_REG_INVALID, ORC_REG_INVALID, 0))
    return;

  xinsn = orc_x86_get_output_insn (p);
  orc_avx_insn_from_opcode (xinsn, index, op);
  orc_x86_insn_set_operands (xinsn, op->operands,
      ORC_X86_INSN_OPERAND_SIZE_NONE, dest, src, ORC_REG_INVALID,
      ORC_REG_INVALID);
  orc_x86_insn_set_mem (xinsn, op->operands, size,
      ORC_X86_INSN_OPERAND_TYPE_IDX, dest, src, ORC_REG_INVALID,
      ORC_REG_INVALID);
  orc_x86_insn_set_imm (xinsn, op->operands, ORC_X86_INSN_OPERAND_SIZE_8, imm);
  xinsn->offset = offset;
  xinsn->index_reg = src_index;
  xinsn->shift = shift;
}
