* configure.ac: Add mips*-sde-elf* target.
[deliverable/binutils-gdb.git] / opcodes / i386-dis.c
index e7fff65ae02b72e8912a4f6968fb54c6c73128bc..509cc5d38a3b92f2e6af9e4a10f7868b90099ef6 100644 (file)
@@ -1,6 +1,6 @@
 /* Print i386 instructions for GDB, the GNU debugger.
    Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 /* Print i386 instructions for GDB, the GNU debugger.
    Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
    This file is part of GDB.
 
@@ -35,7 +35,7 @@
 #include "sysdep.h"
 #include "opintl.h"
 
 #include "sysdep.h"
 #include "opintl.h"
 
-#define MAXLEN 20
+#define MAXLEN 15
 
 #include <setjmp.h>
 
 
 #include <setjmp.h>
 
@@ -85,13 +85,16 @@ static void OP_MMX (int, int);
 static void OP_XMM (int, int);
 static void OP_EM (int, int);
 static void OP_EX (int, int);
 static void OP_XMM (int, int);
 static void OP_EM (int, int);
 static void OP_EX (int, int);
+static void OP_EMC (int,int);
+static void OP_MXC (int,int);
 static void OP_MS (int, int);
 static void OP_XS (int, int);
 static void OP_M (int, int);
 static void OP_VMX (int, int);
 static void OP_0fae (int, int);
 static void OP_0f07 (int, int);
 static void OP_MS (int, int);
 static void OP_XS (int, int);
 static void OP_M (int, int);
 static void OP_VMX (int, int);
 static void OP_0fae (int, int);
 static void OP_0f07 (int, int);
-static void NOP_Fixup (int, int);
+static void NOP_Fixup1 (int, int);
+static void NOP_Fixup2 (int, int);
 static void OP_3DNowSuffix (int, int);
 static void OP_SIMD_Suffix (int, int);
 static void SIMD_Fixup (int, int);
 static void OP_3DNowSuffix (int, int);
 static void OP_SIMD_Suffix (int, int);
 static void SIMD_Fixup (int, int);
@@ -99,8 +102,9 @@ static void PNI_Fixup (int, int);
 static void SVME_Fixup (int, int);
 static void INVLPG_Fixup (int, int);
 static void BadOp (void);
 static void SVME_Fixup (int, int);
 static void INVLPG_Fixup (int, int);
 static void BadOp (void);
-static void SEG_Fixup (int, int);
 static void VMX_Fixup (int, int);
 static void VMX_Fixup (int, int);
+static void REP_Fixup (int, int);
+static void CMPXCHG8B_Fixup (int, int);
 
 struct dis_private {
   /* Points to first byte not fetched.  */
 
 struct dis_private {
   /* Points to first byte not fetched.  */
@@ -115,8 +119,14 @@ struct dis_private {
    when we can.  */
 #define FWAIT_OPCODE (0x9b)
 
    when we can.  */
 #define FWAIT_OPCODE (0x9b)
 
-/* Set to 1 for 64bit mode disassembly.  */
-static int mode_64bit;
+enum address_mode
+{
+  mode_16bit,
+  mode_32bit,
+  mode_64bit
+};
+
+enum address_mode address_mode;
 
 /* Flags for the prefixes for the current instruction.  See below.  */
 static int prefixes;
 
 /* Flags for the prefixes for the current instruction.  See below.  */
 static int prefixes;
@@ -173,10 +183,13 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
   struct dis_private *priv = (struct dis_private *) info->private_data;
   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
 
   struct dis_private *priv = (struct dis_private *) info->private_data;
   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
 
-  status = (*info->read_memory_func) (start,
-                                     priv->max_fetched,
-                                     addr - priv->max_fetched,
-                                     info);
+  if (addr <= priv->the_buffer + MAXLEN)
+    status = (*info->read_memory_func) (start,
+                                       priv->max_fetched,
+                                       addr - priv->max_fetched,
+                                       info);
+  else
+    status = -1;
   if (status != 0)
     {
       /* If we did manage to read at least one byte, then
   if (status != 0)
     {
       /* If we did manage to read at least one byte, then
@@ -197,16 +210,17 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Eb OP_E, b_mode
 #define Ev OP_E, v_mode
 #define Ed OP_E, d_mode
 #define Eb OP_E, b_mode
 #define Ev OP_E, v_mode
 #define Ed OP_E, d_mode
-#define Eq OP_E, q_mode
 #define Edq OP_E, dq_mode
 #define Edqw OP_E, dqw_mode
 #define Edq OP_E, dq_mode
 #define Edqw OP_E, dqw_mode
-#define indirEv OP_indirE, branch_v_mode
+#define indirEv OP_indirE, stack_v_mode
 #define indirEp OP_indirE, f_mode
 #define indirEp OP_indirE, f_mode
+#define stackEv OP_E, stack_v_mode
 #define Em OP_E, m_mode
 #define Ew OP_E, w_mode
 #define Em OP_E, m_mode
 #define Ew OP_E, w_mode
-#define Ma OP_E, v_mode
 #define M OP_M, 0              /* lea, lgdt, etc. */
 #define M OP_M, 0              /* lea, lgdt, etc. */
+#define Ma OP_M, v_mode
 #define Mp OP_M, f_mode                /* 32 or 48 bit memory operand for LDS, LES etc */
 #define Mp OP_M, f_mode                /* 32 or 48 bit memory operand for LDS, LES etc */
+#define Mq OP_M, q_mode
 #define Gb OP_G, b_mode
 #define Gv OP_G, v_mode
 #define Gd OP_G, d_mode
 #define Gb OP_G, b_mode
 #define Gv OP_G, v_mode
 #define Gd OP_G, d_mode
@@ -227,7 +241,6 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Cm OP_C, m_mode
 #define Dm OP_D, m_mode
 #define Td OP_T, d_mode
 #define Cm OP_C, m_mode
 #define Dm OP_D, m_mode
 #define Td OP_T, d_mode
-#define Sv SEG_Fixup, v_mode
 
 #define RMeAX OP_REG, eAX_reg
 #define RMeBX OP_REG, eBX_reg
 
 #define RMeAX OP_REG, eAX_reg
 #define RMeBX OP_REG, eBX_reg
@@ -266,7 +279,6 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define eSI OP_IMREG, eSI_reg
 #define eDI OP_IMREG, eDI_reg
 #define AL OP_IMREG, al_reg
 #define eSI OP_IMREG, eSI_reg
 #define eDI OP_IMREG, eDI_reg
 #define AL OP_IMREG, al_reg
-#define AL OP_IMREG, al_reg
 #define CL OP_IMREG, cl_reg
 #define DL OP_IMREG, dl_reg
 #define BL OP_IMREG, bl_reg
 #define CL OP_IMREG, cl_reg
 #define DL OP_IMREG, dl_reg
 #define BL OP_IMREG, bl_reg
@@ -276,16 +288,17 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define BH OP_IMREG, bh_reg
 #define AX OP_IMREG, ax_reg
 #define DX OP_IMREG, dx_reg
 #define BH OP_IMREG, bh_reg
 #define AX OP_IMREG, ax_reg
 #define DX OP_IMREG, dx_reg
+#define zAX OP_IMREG, z_mode_ax_reg
 #define indirDX OP_IMREG, indir_dx_reg
 
 #define Sw OP_SEG, w_mode
 #define indirDX OP_IMREG, indir_dx_reg
 
 #define Sw OP_SEG, w_mode
+#define Sv OP_SEG, v_mode
 #define Ap OP_DIR, 0
 #define Ap OP_DIR, 0
-#define Ob OP_OFF, b_mode
-#define Ob64 OP_OFF64, b_mode
-#define Ov OP_OFF, v_mode
-#define Ov64 OP_OFF64, v_mode
+#define Ob OP_OFF64, b_mode
+#define Ov OP_OFF64, v_mode
 #define Xb OP_DSreg, eSI_reg
 #define Xv OP_DSreg, eSI_reg
 #define Xb OP_DSreg, eSI_reg
 #define Xv OP_DSreg, eSI_reg
+#define Xz OP_DSreg, eSI_reg
 #define Yb OP_ESreg, eDI_reg
 #define Yv OP_ESreg, eDI_reg
 #define DSBX OP_DSreg, eBX_reg
 #define Yb OP_ESreg, eDI_reg
 #define Yv OP_ESreg, eDI_reg
 #define DSBX OP_DSreg, eBX_reg
@@ -303,10 +316,22 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define EX OP_EX, v_mode
 #define MS OP_MS, v_mode
 #define XS OP_XS, v_mode
 #define EX OP_EX, v_mode
 #define MS OP_MS, v_mode
 #define XS OP_XS, v_mode
+#define EMC OP_EMC, v_mode
+#define MXC OP_MXC, 0
 #define VM OP_VMX, q_mode
 #define OPSUF OP_3DNowSuffix, 0
 #define OPSIMD OP_SIMD_Suffix, 0
 
 #define VM OP_VMX, q_mode
 #define OPSUF OP_3DNowSuffix, 0
 #define OPSIMD OP_SIMD_Suffix, 0
 
+/* Used handle "rep" prefix for string instructions.  */
+#define Xbr REP_Fixup, eSI_reg
+#define Xvr REP_Fixup, eSI_reg
+#define Ybr REP_Fixup, eDI_reg
+#define Yvr REP_Fixup, eDI_reg
+#define Yzr REP_Fixup, eDI_reg
+#define indirDXr REP_Fixup, indir_dx_reg
+#define ALr REP_Fixup, al_reg
+#define eAXr REP_Fixup, eAX_reg
+
 #define cond_jump_flag NULL, cond_jump_mode
 #define loop_jcxz_flag NULL, loop_jcxz_mode
 
 #define cond_jump_flag NULL, cond_jump_mode
 #define loop_jcxz_flag NULL, loop_jcxz_mode
 
@@ -329,7 +354,9 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define dqw_mode 12 /* registers like dq_mode, memory like w_mode.  */
 #define f_mode 13 /* 4- or 6-byte pointer operand */
 #define const_1_mode 14
 #define dqw_mode 12 /* registers like dq_mode, memory like w_mode.  */
 #define f_mode 13 /* 4- or 6-byte pointer operand */
 #define const_1_mode 14
-#define branch_v_mode 15 /* v_mode for branch.  */
+#define stack_v_mode 15 /* v_mode for stack-related opcodes.  */
+#define z_mode 16 /* non-quad operand size depends on prefixes */
+#define o_mode 17  /* 16-byte operand */
 
 #define es_reg 100
 #define cs_reg 101
 
 #define es_reg 100
 #define cs_reg 101
@@ -374,76 +401,92 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define rSI_reg 138
 #define rDI_reg 139
 
 #define rSI_reg 138
 #define rDI_reg 139
 
+#define z_mode_ax_reg 149
 #define indir_dx_reg 150
 
 #define FLOATCODE 1
 #define USE_GROUPS 2
 #define USE_PREFIX_USER_TABLE 3
 #define X86_64_SPECIAL 4
 #define indir_dx_reg 150
 
 #define FLOATCODE 1
 #define USE_GROUPS 2
 #define USE_PREFIX_USER_TABLE 3
 #define X86_64_SPECIAL 4
-
-#define FLOAT    NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
-
-#define GRP1b    NULL, NULL, USE_GROUPS, NULL,  0, NULL, 0
-#define GRP1S    NULL, NULL, USE_GROUPS, NULL,  1, NULL, 0
-#define GRP1Ss   NULL, NULL, USE_GROUPS, NULL,  2, NULL, 0
-#define GRP2b    NULL, NULL, USE_GROUPS, NULL,  3, NULL, 0
-#define GRP2S    NULL, NULL, USE_GROUPS, NULL,  4, NULL, 0
-#define GRP2b_one NULL, NULL, USE_GROUPS, NULL,  5, NULL, 0
-#define GRP2S_one NULL, NULL, USE_GROUPS, NULL,  6, NULL, 0
-#define GRP2b_cl  NULL, NULL, USE_GROUPS, NULL,  7, NULL, 0
-#define GRP2S_cl  NULL, NULL, USE_GROUPS, NULL,  8, NULL, 0
-#define GRP3b    NULL, NULL, USE_GROUPS, NULL,  9, NULL, 0
-#define GRP3S    NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0
-#define GRP4     NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0
-#define GRP5     NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0
-#define GRP6     NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0
-#define GRP7     NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0
-#define GRP8     NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0
-#define GRP9     NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0
-#define GRP10    NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0
-#define GRP11    NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0
-#define GRP12    NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0
-#define GRP13    NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0
-#define GRP14    NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0
-#define GRPAMD   NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0
-#define GRPPADLCK1 NULL, NULL, USE_GROUPS, NULL, 23, NULL, 0
-#define GRPPADLCK2 NULL, NULL, USE_GROUPS, NULL, 24, NULL, 0
-
-#define PREGRP0   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  0, NULL, 0
-#define PREGRP1   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  1, NULL, 0
-#define PREGRP2   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  2, NULL, 0
-#define PREGRP3   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  3, NULL, 0
-#define PREGRP4   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  4, NULL, 0
-#define PREGRP5   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  5, NULL, 0
-#define PREGRP6   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  6, NULL, 0
-#define PREGRP7   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  7, NULL, 0
-#define PREGRP8   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  8, NULL, 0
-#define PREGRP9   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  9, NULL, 0
-#define PREGRP10  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0
-#define PREGRP11  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0
-#define PREGRP12  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0
-#define PREGRP13  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0
-#define PREGRP14  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0
-#define PREGRP15  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0
-#define PREGRP16  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0
-#define PREGRP17  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0
-#define PREGRP18  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0
-#define PREGRP19  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0
-#define PREGRP20  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0
-#define PREGRP21  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0
-#define PREGRP22  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0
-#define PREGRP23  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0
-#define PREGRP24  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0
-#define PREGRP25  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0
-#define PREGRP26  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0
-#define PREGRP27  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 27, NULL, 0
-#define PREGRP28  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 28, NULL, 0
-#define PREGRP29  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 29, NULL, 0
-#define PREGRP30  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 30, NULL, 0
-#define PREGRP31  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 31, NULL, 0
-#define PREGRP32  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 32, NULL, 0
-
-#define X86_64_0  NULL, NULL, X86_64_SPECIAL, NULL,  0, NULL, 0
+#define IS_3BYTE_OPCODE 5
+
+#define FLOAT    NULL, NULL, FLOATCODE, NULL, 0, NULL, 0, NULL, 0
+
+#define GRP1b    NULL, NULL, USE_GROUPS, NULL,  0, NULL, 0, NULL, 0
+#define GRP1S    NULL, NULL, USE_GROUPS, NULL,  1, NULL, 0, NULL, 0
+#define GRP1Ss   NULL, NULL, USE_GROUPS, NULL,  2, NULL, 0, NULL, 0
+#define GRP2b    NULL, NULL, USE_GROUPS, NULL,  3, NULL, 0, NULL, 0
+#define GRP2S    NULL, NULL, USE_GROUPS, NULL,  4, NULL, 0, NULL, 0
+#define GRP2b_one NULL, NULL, USE_GROUPS, NULL,  5, NULL, 0, NULL, 0
+#define GRP2S_one NULL, NULL, USE_GROUPS, NULL,  6, NULL, 0, NULL, 0
+#define GRP2b_cl  NULL, NULL, USE_GROUPS, NULL,  7, NULL, 0, NULL, 0
+#define GRP2S_cl  NULL, NULL, USE_GROUPS, NULL,  8, NULL, 0, NULL, 0
+#define GRP3b    NULL, NULL, USE_GROUPS, NULL,  9, NULL, 0, NULL, 0
+#define GRP3S    NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0, NULL, 0
+#define GRP4     NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0, NULL, 0
+#define GRP5     NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0, NULL, 0
+#define GRP6     NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0, NULL, 0
+#define GRP7     NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0, NULL, 0
+#define GRP8     NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0, NULL, 0
+#define GRP9     NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0, NULL, 0
+#define GRP11_C6  NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0, NULL, 0
+#define GRP11_C7  NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0, NULL, 0
+#define GRP12    NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0, NULL, 0
+#define GRP13    NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0, NULL, 0
+#define GRP14    NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0, NULL, 0
+#define GRP15    NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0, NULL, 0
+#define GRP16    NULL, NULL, USE_GROUPS, NULL, 23, NULL, 0, NULL, 0
+#define GRPAMD   NULL, NULL, USE_GROUPS, NULL, 24, NULL, 0, NULL, 0
+#define GRPPADLCK1 NULL, NULL, USE_GROUPS, NULL, 25, NULL, 0, NULL, 0
+#define GRPPADLCK2 NULL, NULL, USE_GROUPS, NULL, 26, NULL, 0, NULL, 0
+
+#define PREGRP0   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  0, NULL, 0, NULL, 0
+#define PREGRP1   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  1, NULL, 0, NULL, 0
+#define PREGRP2   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  2, NULL, 0, NULL, 0
+#define PREGRP3   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  3, NULL, 0, NULL, 0
+#define PREGRP4   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  4, NULL, 0, NULL, 0
+#define PREGRP5   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  5, NULL, 0, NULL, 0
+#define PREGRP6   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  6, NULL, 0, NULL, 0
+#define PREGRP7   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  7, NULL, 0, NULL, 0
+#define PREGRP8   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  8, NULL, 0, NULL, 0
+#define PREGRP9   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  9, NULL, 0, NULL, 0
+#define PREGRP10  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0, NULL, 0
+#define PREGRP11  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0, NULL, 0
+#define PREGRP12  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0, NULL, 0
+#define PREGRP13  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0, NULL, 0
+#define PREGRP14  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0, NULL, 0
+#define PREGRP15  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0, NULL, 0
+#define PREGRP16  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0, NULL, 0
+#define PREGRP17  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0, NULL, 0
+#define PREGRP18  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0, NULL, 0
+#define PREGRP19  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0, NULL, 0
+#define PREGRP20  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0, NULL, 0
+#define PREGRP21  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0, NULL, 0
+#define PREGRP22  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0, NULL, 0
+#define PREGRP23  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0, NULL, 0
+#define PREGRP24  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0, NULL, 0
+#define PREGRP25  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0, NULL, 0
+#define PREGRP26  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0, NULL, 0
+#define PREGRP27  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 27, NULL, 0, NULL, 0
+#define PREGRP28  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 28, NULL, 0, NULL, 0
+#define PREGRP29  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 29, NULL, 0, NULL, 0
+#define PREGRP30  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 30, NULL, 0, NULL, 0
+#define PREGRP31  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 31, NULL, 0, NULL, 0
+#define PREGRP32  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 32, NULL, 0, NULL, 0
+#define PREGRP33  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 33, NULL, 0, NULL, 0
+#define PREGRP34  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 34, NULL, 0, NULL, 0
+#define PREGRP35  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 35, NULL, 0, NULL, 0
+#define PREGRP36  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 36, NULL, 0, NULL, 0
+#define PREGRP37  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 37, NULL, 0, NULL, 0
+
+
+#define X86_64_0  NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0, NULL, 0
+#define X86_64_1  NULL, NULL, X86_64_SPECIAL, NULL, 1, NULL, 0, NULL, 0
+#define X86_64_2  NULL, NULL, X86_64_SPECIAL, NULL, 2, NULL, 0, NULL, 0
+#define X86_64_3  NULL, NULL, X86_64_SPECIAL, NULL, 3, NULL, 0, NULL, 0
+
+#define THREE_BYTE_0 NULL, NULL, IS_3BYTE_OPCODE, NULL, 0, NULL, 0, NULL, 0
+#define THREE_BYTE_1 NULL, NULL, IS_3BYTE_OPCODE, NULL, 1, NULL, 0, NULL, 0
 
 typedef void (*op_rtn) (int bytemode, int sizeflag);
 
 
 typedef void (*op_rtn) (int bytemode, int sizeflag);
 
@@ -455,6 +498,8 @@ struct dis386 {
   int bytemode2;
   op_rtn op3;
   int bytemode3;
   int bytemode2;
   op_rtn op3;
   int bytemode3;
+  op_rtn op4;
+  int bytemode4;
 };
 
 /* Upper case letters in the instruction names here are macros.
 };
 
 /* Upper case letters in the instruction names here are macros.
@@ -462,26 +507,31 @@ struct dis386 {
    'B' => print 'b' if suffix_always is true
    'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand
    .      size prefix
    'B' => print 'b' if suffix_always is true
    'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand
    .      size prefix
+   'D' => print 'w' if no register operands or 'w', 'l' or 'q', if
+   .      suffix_always is true
    'E' => print 'e' if 32-bit form of jcxz
    'F' => print 'w' or 'l' depending on address size prefix (loop insns)
    'E' => print 'e' if 32-bit form of jcxz
    'F' => print 'w' or 'l' depending on address size prefix (loop insns)
+   'G' => print 'w' or 'l' depending on operand size prefix (i/o insns)
    'H' => print ",pt" or ",pn" branch hint
    'I' => honor following macro letter even in Intel mode (implemented only
    .      for some of the macro letters)
    'J' => print 'l'
    'L' => print 'l' if suffix_always is true
    'N' => print 'n' if instruction has no wait "prefix"
    'H' => print ",pt" or ",pn" branch hint
    'I' => honor following macro letter even in Intel mode (implemented only
    .      for some of the macro letters)
    'J' => print 'l'
    'L' => print 'l' if suffix_always is true
    'N' => print 'n' if instruction has no wait "prefix"
-   'O' => print 'd', or 'o'
+   'O' => print 'd' or 'o' (or 'q' in Intel mode)
    'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
    .      or suffix_always is true.  print 'q' if rex prefix is present.
    'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
    .      is true
    'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
    .      or suffix_always is true.  print 'q' if rex prefix is present.
    'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
    .      is true
-   'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
+   'R' => print 'w', 'l' or 'q' ('d' for 'l' and 'e' in Intel mode)
    'S' => print 'w', 'l' or 'q' if suffix_always is true
    'T' => print 'q' in 64bit mode and behave as 'P' otherwise
    'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
    'S' => print 'w', 'l' or 'q' if suffix_always is true
    'T' => print 'q' in 64bit mode and behave as 'P' otherwise
    'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
-   'W' => print 'b' or 'w' ("w" or "de" in intel mode)
+   'V' => print 'q' in 64bit mode and behave as 'S' otherwise
+   'W' => print 'b', 'w' or 'l' ('d' in Intel mode)
    'X' => print 's', 'd' depending on data16 prefix (for XMM)
    'Y' => 'q' if instruction has an REX 64bit overwrite prefix
    'X' => print 's', 'd' depending on data16 prefix (for XMM)
    'Y' => 'q' if instruction has an REX 64bit overwrite prefix
+   'Z' => print 'q' in 64bit mode and behave as 'L' otherwise
 
    Many of the above letters print nothing in Intel mode.  See "putop"
    for the details.
 
    Many of the above letters print nothing in Intel mode.  See "putop"
    for the details.
@@ -494,248 +544,248 @@ struct dis386 {
 
 static const struct dis386 dis386[] = {
   /* 00 */
 
 static const struct dis386 dis386[] = {
   /* 00 */
-  { "addB",            Eb, Gb, XX },
-  { "addS",            Ev, Gv, XX },
-  { "addB",            Gb, Eb, XX },
-  { "addS",            Gv, Ev, XX },
-  { "addB",            AL, Ib, XX },
-  { "addS",            eAX, Iv, XX },
-  { "push{T|}",                es, XX, XX },
-  { "pop{T|}",         es, XX, XX },
+  { "addB",            Eb, Gb, XX, XX },
+  { "addS",            Ev, Gv, XX, XX },
+  { "addB",            Gb, Eb, XX, XX },
+  { "addS",            Gv, Ev, XX, XX },
+  { "addB",            AL, Ib, XX, XX },
+  { "addS",            eAX, Iv, XX, XX },
+  { "push{T|}",                es, XX, XX, XX },
+  { "pop{T|}",         es, XX, XX, XX },
   /* 08 */
   /* 08 */
-  { "orB",             Eb, Gb, XX },
-  { "orS",             Ev, Gv, XX },
-  { "orB",             Gb, Eb, XX },
-  { "orS",             Gv, Ev, XX },
-  { "orB",             AL, Ib, XX },
-  { "orS",             eAX, Iv, XX },
-  { "push{T|}",                cs, XX, XX },
-  { "(bad)",           XX, XX, XX },   /* 0x0f extended opcode escape */
+  { "orB",             Eb, Gb, XX, XX },
+  { "orS",             Ev, Gv, XX, XX },
+  { "orB",             Gb, Eb, XX, XX },
+  { "orS",             Gv, Ev, XX, XX },
+  { "orB",             AL, Ib, XX, XX },
+  { "orS",             eAX, Iv, XX, XX },
+  { "push{T|}",                cs, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },       /* 0x0f extended opcode escape */
   /* 10 */
   /* 10 */
-  { "adcB",            Eb, Gb, XX },
-  { "adcS",            Ev, Gv, XX },
-  { "adcB",            Gb, Eb, XX },
-  { "adcS",            Gv, Ev, XX },
-  { "adcB",            AL, Ib, XX },
-  { "adcS",            eAX, Iv, XX },
-  { "push{T|}",                ss, XX, XX },
-  { "popT|}",          ss, XX, XX },
+  { "adcB",            Eb, Gb, XX, XX },
+  { "adcS",            Ev, Gv, XX, XX },
+  { "adcB",            Gb, Eb, XX, XX },
+  { "adcS",            Gv, Ev, XX, XX },
+  { "adcB",            AL, Ib, XX, XX },
+  { "adcS",            eAX, Iv, XX, XX },
+  { "push{T|}",                ss, XX, XX, XX },
+  { "pop{T|}",         ss, XX, XX, XX },
   /* 18 */
   /* 18 */
-  { "sbbB",            Eb, Gb, XX },
-  { "sbbS",            Ev, Gv, XX },
-  { "sbbB",            Gb, Eb, XX },
-  { "sbbS",            Gv, Ev, XX },
-  { "sbbB",            AL, Ib, XX },
-  { "sbbS",            eAX, Iv, XX },
-  { "push{T|}",                ds, XX, XX },
-  { "pop{T|}",         ds, XX, XX },
+  { "sbbB",            Eb, Gb, XX, XX },
+  { "sbbS",            Ev, Gv, XX, XX },
+  { "sbbB",            Gb, Eb, XX, XX },
+  { "sbbS",            Gv, Ev, XX, XX },
+  { "sbbB",            AL, Ib, XX, XX },
+  { "sbbS",            eAX, Iv, XX, XX },
+  { "push{T|}",                ds, XX, XX, XX },
+  { "pop{T|}",         ds, XX, XX, XX },
   /* 20 */
   /* 20 */
-  { "andB",            Eb, Gb, XX },
-  { "andS",            Ev, Gv, XX },
-  { "andB",            Gb, Eb, XX },
-  { "andS",            Gv, Ev, XX },
-  { "andB",            AL, Ib, XX },
-  { "andS",            eAX, Iv, XX },
-  { "(bad)",           XX, XX, XX },   /* SEG ES prefix */
-  { "daa{|}",          XX, XX, XX },
+  { "andB",            Eb, Gb, XX, XX },
+  { "andS",            Ev, Gv, XX, XX },
+  { "andB",            Gb, Eb, XX, XX },
+  { "andS",            Gv, Ev, XX, XX },
+  { "andB",            AL, Ib, XX, XX },
+  { "andS",            eAX, Iv, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },       /* SEG ES prefix */
+  { "daa{|}",          XX, XX, XX, XX },
   /* 28 */
   /* 28 */
-  { "subB",            Eb, Gb, XX },
-  { "subS",            Ev, Gv, XX },
-  { "subB",            Gb, Eb, XX },
-  { "subS",            Gv, Ev, XX },
-  { "subB",            AL, Ib, XX },
-  { "subS",            eAX, Iv, XX },
-  { "(bad)",           XX, XX, XX },   /* SEG CS prefix */
-  { "das{|}",          XX, XX, XX },
+  { "subB",            Eb, Gb, XX, XX },
+  { "subS",            Ev, Gv, XX, XX },
+  { "subB",            Gb, Eb, XX, XX },
+  { "subS",            Gv, Ev, XX, XX },
+  { "subB",            AL, Ib, XX, XX },
+  { "subS",            eAX, Iv, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },       /* SEG CS prefix */
+  { "das{|}",          XX, XX, XX, XX },
   /* 30 */
   /* 30 */
-  { "xorB",            Eb, Gb, XX },
-  { "xorS",            Ev, Gv, XX },
-  { "xorB",            Gb, Eb, XX },
-  { "xorS",            Gv, Ev, XX },
-  { "xorB",            AL, Ib, XX },
-  { "xorS",            eAX, Iv, XX },
-  { "(bad)",           XX, XX, XX },   /* SEG SS prefix */
-  { "aaa{|}",          XX, XX, XX },
+  { "xorB",            Eb, Gb, XX, XX },
+  { "xorS",            Ev, Gv, XX, XX },
+  { "xorB",            Gb, Eb, XX, XX },
+  { "xorS",            Gv, Ev, XX, XX },
+  { "xorB",            AL, Ib, XX, XX },
+  { "xorS",            eAX, Iv, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },       /* SEG SS prefix */
+  { "aaa{|}",          XX, XX, XX, XX },
   /* 38 */
   /* 38 */
-  { "cmpB",            Eb, Gb, XX },
-  { "cmpS",            Ev, Gv, XX },
-  { "cmpB",            Gb, Eb, XX },
-  { "cmpS",            Gv, Ev, XX },
-  { "cmpB",            AL, Ib, XX },
-  { "cmpS",            eAX, Iv, XX },
-  { "(bad)",           XX, XX, XX },   /* SEG DS prefix */
-  { "aas{|}",          XX, XX, XX },
+  { "cmpB",            Eb, Gb, XX, XX },
+  { "cmpS",            Ev, Gv, XX, XX },
+  { "cmpB",            Gb, Eb, XX, XX },
+  { "cmpS",            Gv, Ev, XX, XX },
+  { "cmpB",            AL, Ib, XX, XX },
+  { "cmpS",            eAX, Iv, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },       /* SEG DS prefix */
+  { "aas{|}",          XX, XX, XX, XX },
   /* 40 */
   /* 40 */
-  { "inc{S|}",         RMeAX, XX, XX },
-  { "inc{S|}",         RMeCX, XX, XX },
-  { "inc{S|}",         RMeDX, XX, XX },
-  { "inc{S|}",         RMeBX, XX, XX },
-  { "inc{S|}",         RMeSP, XX, XX },
-  { "inc{S|}",         RMeBP, XX, XX },
-  { "inc{S|}",         RMeSI, XX, XX },
-  { "inc{S|}",         RMeDI, XX, XX },
+  { "inc{S|}",         RMeAX, XX, XX, XX },
+  { "inc{S|}",         RMeCX, XX, XX, XX },
+  { "inc{S|}",         RMeDX, XX, XX, XX },
+  { "inc{S|}",         RMeBX, XX, XX, XX },
+  { "inc{S|}",         RMeSP, XX, XX, XX },
+  { "inc{S|}",         RMeBP, XX, XX, XX },
+  { "inc{S|}",         RMeSI, XX, XX, XX },
+  { "inc{S|}",         RMeDI, XX, XX, XX },
   /* 48 */
   /* 48 */
-  { "dec{S|}",         RMeAX, XX, XX },
-  { "dec{S|}",         RMeCX, XX, XX },
-  { "dec{S|}",         RMeDX, XX, XX },
-  { "dec{S|}",         RMeBX, XX, XX },
-  { "dec{S|}",         RMeSP, XX, XX },
-  { "dec{S|}",         RMeBP, XX, XX },
-  { "dec{S|}",         RMeSI, XX, XX },
-  { "dec{S|}",         RMeDI, XX, XX },
+  { "dec{S|}",         RMeAX, XX, XX, XX },
+  { "dec{S|}",         RMeCX, XX, XX, XX },
+  { "dec{S|}",         RMeDX, XX, XX, XX },
+  { "dec{S|}",         RMeBX, XX, XX, XX },
+  { "dec{S|}",         RMeSP, XX, XX, XX },
+  { "dec{S|}",         RMeBP, XX, XX, XX },
+  { "dec{S|}",         RMeSI, XX, XX, XX },
+  { "dec{S|}",         RMeDI, XX, XX, XX },
   /* 50 */
   /* 50 */
-  { "pushS",           RMrAX, XX, XX },
-  { "pushS",           RMrCX, XX, XX },
-  { "pushS",           RMrDX, XX, XX },
-  { "pushS",           RMrBX, XX, XX },
-  { "pushS",           RMrSP, XX, XX },
-  { "pushS",           RMrBP, XX, XX },
-  { "pushS",           RMrSI, XX, XX },
-  { "pushS",           RMrDI, XX, XX },
+  { "pushV",           RMrAX, XX, XX, XX },
+  { "pushV",           RMrCX, XX, XX, XX },
+  { "pushV",           RMrDX, XX, XX, XX },
+  { "pushV",           RMrBX, XX, XX, XX },
+  { "pushV",           RMrSP, XX, XX, XX },
+  { "pushV",           RMrBP, XX, XX, XX },
+  { "pushV",           RMrSI, XX, XX, XX },
+  { "pushV",           RMrDI, XX, XX, XX },
   /* 58 */
   /* 58 */
-  { "popS",            RMrAX, XX, XX },
-  { "popS",            RMrCX, XX, XX },
-  { "popS",            RMrDX, XX, XX },
-  { "popS",            RMrBX, XX, XX },
-  { "popS",            RMrSP, XX, XX },
-  { "popS",            RMrBP, XX, XX },
-  { "popS",            RMrSI, XX, XX },
-  { "popS",            RMrDI, XX, XX },
+  { "popV",            RMrAX, XX, XX, XX },
+  { "popV",            RMrCX, XX, XX, XX },
+  { "popV",            RMrDX, XX, XX, XX },
+  { "popV",            RMrBX, XX, XX, XX },
+  { "popV",            RMrSP, XX, XX, XX },
+  { "popV",            RMrBP, XX, XX, XX },
+  { "popV",            RMrSI, XX, XX, XX },
+  { "popV",            RMrDI, XX, XX, XX },
   /* 60 */
   /* 60 */
-  { "pusha{P|}",       XX, XX, XX },
-  { "popa{P|}",                XX, XX, XX },
-  { "bound{S|}",       Gv, Ma, XX },
   { X86_64_0 },
   { X86_64_0 },
-  { "(bad)",           XX, XX, XX },   /* seg fs */
-  { "(bad)",           XX, XX, XX },   /* seg gs */
-  { "(bad)",           XX, XX, XX },   /* op size prefix */
-  { "(bad)",           XX, XX, XX },   /* adr size prefix */
+  { X86_64_1 },
+  { X86_64_2 },
+  { X86_64_3 },
+  { "(bad)",           XX, XX, XX, XX },       /* seg fs */
+  { "(bad)",           XX, XX, XX, XX },       /* seg gs */
+  { "(bad)",           XX, XX, XX, XX },       /* op size prefix */
+  { "(bad)",           XX, XX, XX, XX },       /* adr size prefix */
   /* 68 */
   /* 68 */
-  { "pushT",           Iq, XX, XX },
-  { "imulS",           Gv, Ev, Iv },
-  { "pushT",           sIb, XX, XX },
-  { "imulS",           Gv, Ev, sIb },
-  { "ins{b||b|}",      Yb, indirDX, XX },
-  { "ins{R||R|}",      Yv, indirDX, XX },
-  { "outs{b||b|}",     indirDX, Xb, XX },
-  { "outs{R||R|}",     indirDX, Xv, XX },
+  { "pushT",           Iq, XX, XX, XX },
+  { "imulS",           Gv, Ev, Iv, XX },
+  { "pushT",           sIb, XX, XX, XX },
+  { "imulS",           Gv, Ev, sIb, XX },
+  { "ins{b||b|}",      Ybr, indirDX, XX, XX },
+  { "ins{R||G|}",      Yzr, indirDX, XX, XX },
+  { "outs{b||b|}",     indirDXr, Xb, XX, XX },
+  { "outs{R||G|}",     indirDXr, Xz, XX, XX },
   /* 70 */
   /* 70 */
-  { "joH",             Jb, XX, cond_jump_flag },
-  { "jnoH",            Jb, XX, cond_jump_flag },
-  { "jbH",             Jb, XX, cond_jump_flag },
-  { "jaeH",            Jb, XX, cond_jump_flag },
-  { "jeH",             Jb, XX, cond_jump_flag },
-  { "jneH",            Jb, XX, cond_jump_flag },
-  { "jbeH",            Jb, XX, cond_jump_flag },
-  { "jaH",             Jb, XX, cond_jump_flag },
+  { "joH",             Jb, XX, cond_jump_flag, XX },
+  { "jnoH",            Jb, XX, cond_jump_flag, XX },
+  { "jbH",             Jb, XX, cond_jump_flag, XX },
+  { "jaeH",            Jb, XX, cond_jump_flag, XX },
+  { "jeH",             Jb, XX, cond_jump_flag, XX },
+  { "jneH",            Jb, XX, cond_jump_flag, XX },
+  { "jbeH",            Jb, XX, cond_jump_flag, XX },
+  { "jaH",             Jb, XX, cond_jump_flag, XX },
   /* 78 */
   /* 78 */
-  { "jsH",             Jb, XX, cond_jump_flag },
-  { "jnsH",            Jb, XX, cond_jump_flag },
-  { "jpH",             Jb, XX, cond_jump_flag },
-  { "jnpH",            Jb, XX, cond_jump_flag },
-  { "jlH",             Jb, XX, cond_jump_flag },
-  { "jgeH",            Jb, XX, cond_jump_flag },
-  { "jleH",            Jb, XX, cond_jump_flag },
-  { "jgH",             Jb, XX, cond_jump_flag },
+  { "jsH",             Jb, XX, cond_jump_flag, XX },
+  { "jnsH",            Jb, XX, cond_jump_flag, XX },
+  { "jpH",             Jb, XX, cond_jump_flag, XX },
+  { "jnpH",            Jb, XX, cond_jump_flag, XX },
+  { "jlH",             Jb, XX, cond_jump_flag, XX },
+  { "jgeH",            Jb, XX, cond_jump_flag, XX },
+  { "jleH",            Jb, XX, cond_jump_flag, XX },
+  { "jgH",             Jb, XX, cond_jump_flag, XX },
   /* 80 */
   { GRP1b },
   { GRP1S },
   /* 80 */
   { GRP1b },
   { GRP1S },
-  { "(bad)",           XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
   { GRP1Ss },
   { GRP1Ss },
-  { "testB",           Eb, Gb, XX },
-  { "testS",           Ev, Gv, XX },
-  { "xchgB",           Eb, Gb, XX },
-  { "xchgS",           Ev, Gv, XX },
+  { "testB",           Eb, Gb, XX, XX },
+  { "testS",           Ev, Gv, XX, XX },
+  { "xchgB",           Eb, Gb, XX, XX },
+  { "xchgS",           Ev, Gv, XX, XX },
   /* 88 */
   /* 88 */
-  { "movB",            Eb, Gb, XX },
-  { "movS",            Ev, Gv, XX },
-  { "movB",            Gb, Eb, XX },
-  { "movS",            Gv, Ev, XX },
-  { "movQ",            Sv, Sw, XX },
-  { "leaS",            Gv, M, XX },
-  { "movQ",            Sw, Sv, XX },
-  { "popU",            Ev, XX, XX },
+  { "movB",            Eb, Gb, XX, XX },
+  { "movS",            Ev, Gv, XX, XX },
+  { "movB",            Gb, Eb, XX, XX },
+  { "movS",            Gv, Ev, XX, XX },
+  { "movD",            Sv, Sw, XX, XX },
+  { "leaS",            Gv, M, XX, XX },
+  { "movD",            Sw, Sv, XX, XX },
+  { "popU",            stackEv, XX, XX, XX },
   /* 90 */
   /* 90 */
-  { "nop",             NOP_Fixup, 0, XX, XX },
-  { "xchgS",           RMeCX, eAX, XX },
-  { "xchgS",           RMeDX, eAX, XX },
-  { "xchgS",           RMeBX, eAX, XX },
-  { "xchgS",           RMeSP, eAX, XX },
-  { "xchgS",           RMeBP, eAX, XX },
-  { "xchgS",           RMeSI, eAX, XX },
-  { "xchgS",           RMeDI, eAX, XX },
+  { "xchgS",           NOP_Fixup1, eAX_reg, NOP_Fixup2, eAX_reg, XX, XX },
+  { "xchgS",           RMeCX, eAX, XX, XX },
+  { "xchgS",           RMeDX, eAX, XX, XX },
+  { "xchgS",           RMeBX, eAX, XX, XX },
+  { "xchgS",           RMeSP, eAX, XX, XX },
+  { "xchgS",           RMeBP, eAX, XX, XX },
+  { "xchgS",           RMeSI, eAX, XX, XX },
+  { "xchgS",           RMeDI, eAX, XX, XX },
   /* 98 */
   /* 98 */
-  { "cW{tR||tR|}",     XX, XX, XX },
-  { "cR{tO||tO|}",     XX, XX, XX },
-  { "Jcall{T|}",       Ap, XX, XX },
-  { "(bad)",           XX, XX, XX },   /* fwait */
-  { "pushfT",          XX, XX, XX },
-  { "popfT",           XX, XX, XX },
-  { "sahf{|}",         XX, XX, XX },
-  { "lahf{|}",         XX, XX, XX },
+  { "cW{t||t|}R",      XX, XX, XX, XX },
+  { "cR{t||t|}O",      XX, XX, XX, XX },
+  { "Jcall{T|}",       Ap, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },       /* fwait */
+  { "pushfT",          XX, XX, XX, XX },
+  { "popfT",           XX, XX, XX, XX },
+  { "sahf{|}",         XX, XX, XX, XX },
+  { "lahf{|}",         XX, XX, XX, XX },
   /* a0 */
   /* a0 */
-  { "movB",            AL, Ob64, XX },
-  { "movS",            eAX, Ov64, XX },
-  { "movB",            Ob64, AL, XX },
-  { "movS",            Ov64, eAX, XX },
-  { "movs{b||b|}",     Yb, Xb, XX },
-  { "movs{R||R|}",     Yv, Xv, XX },
-  { "cmps{b||b|}",     Xb, Yb, XX },
-  { "cmps{R||R|}",     Xv, Yv, XX },
+  { "movB",            AL, Ob, XX, XX },
+  { "movS",            eAX, Ov, XX, XX },
+  { "movB",            Ob, AL, XX, XX },
+  { "movS",            Ov, eAX, XX, XX },
+  { "movs{b||b|}",     Ybr, Xb, XX, XX },
+  { "movs{R||R|}",     Yvr, Xv, XX, XX },
+  { "cmps{b||b|}",     Xb, Yb, XX, XX },
+  { "cmps{R||R|}",     Xv, Yv, XX, XX },
   /* a8 */
   /* a8 */
-  { "testB",           AL, Ib, XX },
-  { "testS",           eAX, Iv, XX },
-  { "stosB",           Yb, AL, XX },
-  { "stosS",           Yv, eAX, XX },
-  { "lodsB",           AL, Xb, XX },
-  { "lodsS",           eAX, Xv, XX },
-  { "scasB",           AL, Yb, XX },
-  { "scasS",           eAX, Yv, XX },
+  { "testB",           AL, Ib, XX, XX },
+  { "testS",           eAX, Iv, XX, XX },
+  { "stosB",           Ybr, AL, XX, XX },
+  { "stosS",           Yvr, eAX, XX, XX },
+  { "lodsB",           ALr, Xb, XX, XX },
+  { "lodsS",           eAXr, Xv, XX, XX },
+  { "scasB",           AL, Yb, XX, XX },
+  { "scasS",           eAX, Yv, XX, XX },
   /* b0 */
   /* b0 */
-  { "movB",            RMAL, Ib, XX },
-  { "movB",            RMCL, Ib, XX },
-  { "movB",            RMDL, Ib, XX },
-  { "movB",            RMBL, Ib, XX },
-  { "movB",            RMAH, Ib, XX },
-  { "movB",            RMCH, Ib, XX },
-  { "movB",            RMDH, Ib, XX },
-  { "movB",            RMBH, Ib, XX },
+  { "movB",            RMAL, Ib, XX, XX },
+  { "movB",            RMCL, Ib, XX, XX },
+  { "movB",            RMDL, Ib, XX, XX },
+  { "movB",            RMBL, Ib, XX, XX },
+  { "movB",            RMAH, Ib, XX, XX },
+  { "movB",            RMCH, Ib, XX, XX },
+  { "movB",            RMDH, Ib, XX, XX },
+  { "movB",            RMBH, Ib, XX, XX },
   /* b8 */
   /* b8 */
-  { "movS",            RMeAX, Iv64, XX },
-  { "movS",            RMeCX, Iv64, XX },
-  { "movS",            RMeDX, Iv64, XX },
-  { "movS",            RMeBX, Iv64, XX },
-  { "movS",            RMeSP, Iv64, XX },
-  { "movS",            RMeBP, Iv64, XX },
-  { "movS",            RMeSI, Iv64, XX },
-  { "movS",            RMeDI, Iv64, XX },
+  { "movS",            RMeAX, Iv64, XX, XX },
+  { "movS",            RMeCX, Iv64, XX, XX },
+  { "movS",            RMeDX, Iv64, XX, XX },
+  { "movS",            RMeBX, Iv64, XX, XX },
+  { "movS",            RMeSP, Iv64, XX, XX },
+  { "movS",            RMeBP, Iv64, XX, XX },
+  { "movS",            RMeSI, Iv64, XX, XX },
+  { "movS",            RMeDI, Iv64, XX, XX },
   /* c0 */
   { GRP2b },
   { GRP2S },
   /* c0 */
   { GRP2b },
   { GRP2S },
-  { "retT",            Iw, XX, XX },
-  { "retT",            XX, XX, XX },
-  { "les{S|}",         Gv, Mp, XX },
-  { "ldsS",            Gv, Mp, XX },
-  { "movA",            Eb, Ib, XX },
-  { "movQ",            Ev, Iv, XX },
+  { "retT",            Iw, XX, XX, XX },
+  { "retT",            XX, XX, XX, XX },
+  { "les{S|}",         Gv, Mp, XX, XX },
+  { "ldsS",            Gv, Mp, XX, XX },
+  { GRP11_C6 },
+  { GRP11_C7 },
   /* c8 */
   /* c8 */
-  { "enterT",          Iw, Ib, XX },
-  { "leaveT",          XX, XX, XX },
-  { "lretP",           Iw, XX, XX },
-  { "lretP",           XX, XX, XX },
-  { "int3",            XX, XX, XX },
-  { "int",             Ib, XX, XX },
-  { "into{|}",         XX, XX, XX },
-  { "iretP",           XX, XX, XX },
+  { "enterT",          Iw, Ib, XX, XX },
+  { "leaveT",          XX, XX, XX, XX },
+  { "lretP",           Iw, XX, XX, XX },
+  { "lretP",           XX, XX, XX, XX },
+  { "int3",            XX, XX, XX, XX },
+  { "int",             Ib, XX, XX, XX },
+  { "into{|}",         XX, XX, XX, XX },
+  { "iretP",           XX, XX, XX, XX },
   /* d0 */
   { GRP2b_one },
   { GRP2S_one },
   { GRP2b_cl },
   { GRP2S_cl },
   /* d0 */
   { GRP2b_one },
   { GRP2S_one },
   { GRP2b_cl },
   { GRP2S_cl },
-  { "aam{|}",          sIb, XX, XX },
-  { "aad{|}",          sIb, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "xlat",            DSBX, XX, XX },
+  { "aam{|}",          sIb, XX, XX, XX },
+  { "aad{|}",          sIb, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "xlat",            DSBX, XX, XX, XX },
   /* d8 */
   { FLOAT },
   { FLOAT },
   /* d8 */
   { FLOAT },
   { FLOAT },
@@ -746,39 +796,39 @@ static const struct dis386 dis386[] = {
   { FLOAT },
   { FLOAT },
   /* e0 */
   { FLOAT },
   { FLOAT },
   /* e0 */
-  { "loopneFH",                Jb, XX, loop_jcxz_flag },
-  { "loopeFH",         Jb, XX, loop_jcxz_flag },
-  { "loopFH",          Jb, XX, loop_jcxz_flag },
-  { "jEcxzH",          Jb, XX, loop_jcxz_flag },
-  { "inB",             AL, Ib, XX },
-  { "inS",             eAX, Ib, XX },
-  { "outB",            Ib, AL, XX },
-  { "outS",            Ib, eAX, XX },
+  { "loopneFH",                Jb, XX, loop_jcxz_flag, XX },
+  { "loopeFH",         Jb, XX, loop_jcxz_flag, XX },
+  { "loopFH",          Jb, XX, loop_jcxz_flag, XX },
+  { "jEcxzH",          Jb, XX, loop_jcxz_flag, XX },
+  { "inB",             AL, Ib, XX, XX },
+  { "inG",             zAX, Ib, XX, XX },
+  { "outB",            Ib, AL, XX, XX },
+  { "outG",            Ib, zAX, XX, XX },
   /* e8 */
   /* e8 */
-  { "callT",           Jv, XX, XX },
-  { "jmpT",            Jv, XX, XX },
-  { "Jjmp{T|}",                Ap, XX, XX },
-  { "jmp",             Jb, XX, XX },
-  { "inB",             AL, indirDX, XX },
-  { "inS",             eAX, indirDX, XX },
-  { "outB",            indirDX, AL, XX },
-  { "outS",            indirDX, eAX, XX },
+  { "callT",           Jv, XX, XX, XX },
+  { "jmpT",            Jv, XX, XX, XX },
+  { "Jjmp{T|}",                Ap, XX, XX, XX },
+  { "jmp",             Jb, XX, XX, XX },
+  { "inB",             AL, indirDX, XX, XX },
+  { "inG",             zAX, indirDX, XX, XX },
+  { "outB",            indirDX, AL, XX, XX },
+  { "outG",            indirDX, zAX, XX, XX },
   /* f0 */
   /* f0 */
-  { "(bad)",           XX, XX, XX },   /* lock prefix */
-  { "icebp",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },   /* repne */
-  { "(bad)",           XX, XX, XX },   /* repz */
-  { "hlt",             XX, XX, XX },
-  { "cmc",             XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },       /* lock prefix */
+  { "icebp",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },       /* repne */
+  { "(bad)",           XX, XX, XX, XX },       /* repz */
+  { "hlt",             XX, XX, XX, XX },
+  { "cmc",             XX, XX, XX, XX },
   { GRP3b },
   { GRP3S },
   /* f8 */
   { GRP3b },
   { GRP3S },
   /* f8 */
-  { "clc",             XX, XX, XX },
-  { "stc",             XX, XX, XX },
-  { "cli",             XX, XX, XX },
-  { "sti",             XX, XX, XX },
-  { "cld",             XX, XX, XX },
-  { "std",             XX, XX, XX },
+  { "clc",             XX, XX, XX, XX },
+  { "stc",             XX, XX, XX, XX },
+  { "cli",             XX, XX, XX, XX },
+  { "sti",             XX, XX, XX, XX },
+  { "cld",             XX, XX, XX, XX },
+  { "std",             XX, XX, XX, XX },
   { GRP4 },
   { GRP5 },
 };
   { GRP4 },
   { GRP5 },
 };
@@ -787,102 +837,102 @@ static const struct dis386 dis386_twobyte[] = {
   /* 00 */
   { GRP6 },
   { GRP7 },
   /* 00 */
   { GRP6 },
   { GRP7 },
-  { "larS",            Gv, Ew, XX },
-  { "lslS",            Gv, Ew, XX },
-  { "(bad)",           XX, XX, XX },
-  { "syscall",         XX, XX, XX },
-  { "clts",            XX, XX, XX },
-  { "sysretP",         XX, XX, XX },
+  { "larS",            Gv, Ew, XX, XX },
+  { "lslS",            Gv, Ew, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "syscall",         XX, XX, XX, XX },
+  { "clts",            XX, XX, XX, XX },
+  { "sysretP",         XX, XX, XX, XX },
   /* 08 */
   /* 08 */
-  { "invd",            XX, XX, XX },
-  { "wbinvd",          XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "ud2a",            XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
+  { "invd",            XX, XX, XX, XX },
+  { "wbinvd",          XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "ud2a",            XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
   { GRPAMD },
   { GRPAMD },
-  { "femms",           XX, XX, XX },
-  { "",                        MX, EM, OPSUF }, /* See OP_3DNowSuffix.  */
+  { "femms",           XX, XX, XX, XX },
+  { "",                        MX, EM, OPSUF, XX }, /* See OP_3DNowSuffix.  */
   /* 10 */
   { PREGRP8 },
   { PREGRP9 },
   { PREGRP30 },
   /* 10 */
   { PREGRP8 },
   { PREGRP9 },
   { PREGRP30 },
-  { "movlpX",          EX, XM, SIMD_Fixup, 'h' },
-  { "unpcklpX",                XM, EX, XX },
-  { "unpckhpX",                XM, EX, XX },
+  { "movlpX",          EX, XM, SIMD_Fixup, 'h', XX },
+  { "unpcklpX",                XM, EX, XX, XX },
+  { "unpckhpX",                XM, EX, XX, XX },
   { PREGRP31 },
   { PREGRP31 },
-  { "movhpX",          EX, XM, SIMD_Fixup, 'l' },
+  { "movhpX",          EX, XM, SIMD_Fixup, 'l', XX },
   /* 18 */
   /* 18 */
-  { GRP14 },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
+  { GRP16 },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "nopQ",            Ev, XX, XX, XX },
   /* 20 */
   /* 20 */
-  { "movL",            Rm, Cm, XX },
-  { "movL",            Rm, Dm, XX },
-  { "movL",            Cm, Rm, XX },
-  { "movL",            Dm, Rm, XX },
-  { "movL",            Rd, Td, XX },
-  { "(bad)",           XX, XX, XX },
-  { "movL",            Td, Rd, XX },
-  { "(bad)",           XX, XX, XX },
+  { "movZ",            Rm, Cm, XX, XX },
+  { "movZ",            Rm, Dm, XX, XX },
+  { "movZ",            Cm, Rm, XX, XX },
+  { "movZ",            Dm, Rm, XX, XX },
+  { "movL",            Rd, Td, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "movL",            Td, Rd, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
   /* 28 */
   /* 28 */
-  { "movapX",          XM, EX, XX },
-  { "movapX",          EX, XM, XX },
+  { "movapX",          XM, EX, XX, XX },
+  { "movapX",          EX, XM, XX, XX },
   { PREGRP2 },
   { PREGRP2 },
-  { "movntpX",         Ev, XM, XX },
+  { PREGRP33 },
   { PREGRP4 },
   { PREGRP3 },
   { PREGRP4 },
   { PREGRP3 },
-  { "ucomisX",         XM,EX, XX },
-  { "comisX",          XM,EX, XX },
+  { "ucomisX",         XM,EX, XX, XX },
+  { "comisX",          XM,EX, XX, XX },
   /* 30 */
   /* 30 */
-  { "wrmsr",           XX, XX, XX },
-  { "rdtsc",           XX, XX, XX },
-  { "rdmsr",           XX, XX, XX },
-  { "rdpmc",           XX, XX, XX },
-  { "sysenter",                XX, XX, XX },
-  { "sysexit",         XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
+  { "wrmsr",           XX, XX, XX, XX },
+  { "rdtsc",           XX, XX, XX, XX },
+  { "rdmsr",           XX, XX, XX, XX },
+  { "rdpmc",           XX, XX, XX, XX },
+  { "sysenter",                XX, XX, XX, XX },
+  { "sysexit",         XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
   /* 38 */
   /* 38 */
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
+  { THREE_BYTE_0 },
+  { "(bad)",           XX, XX, XX, XX },
+  { THREE_BYTE_1 },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
   /* 40 */
   /* 40 */
-  { "cmovo",           Gv, Ev, XX },
-  { "cmovno",          Gv, Ev, XX },
-  { "cmovb",           Gv, Ev, XX },
-  { "cmovae",          Gv, Ev, XX },
-  { "cmove",           Gv, Ev, XX },
-  { "cmovne",          Gv, Ev, XX },
-  { "cmovbe",          Gv, Ev, XX },
-  { "cmova",           Gv, Ev, XX },
+  { "cmovo",           Gv, Ev, XX, XX },
+  { "cmovno",          Gv, Ev, XX, XX },
+  { "cmovb",           Gv, Ev, XX, XX },
+  { "cmovae",          Gv, Ev, XX, XX },
+  { "cmove",           Gv, Ev, XX, XX },
+  { "cmovne",          Gv, Ev, XX, XX },
+  { "cmovbe",          Gv, Ev, XX, XX },
+  { "cmova",           Gv, Ev, XX, XX },
   /* 48 */
   /* 48 */
-  { "cmovs",           Gv, Ev, XX },
-  { "cmovns",          Gv, Ev, XX },
-  { "cmovp",           Gv, Ev, XX },
-  { "cmovnp",          Gv, Ev, XX },
-  { "cmovl",           Gv, Ev, XX },
-  { "cmovge",          Gv, Ev, XX },
-  { "cmovle",          Gv, Ev, XX },
-  { "cmovg",           Gv, Ev, XX },
+  { "cmovs",           Gv, Ev, XX, XX },
+  { "cmovns",          Gv, Ev, XX, XX },
+  { "cmovp",           Gv, Ev, XX, XX },
+  { "cmovnp",          Gv, Ev, XX, XX },
+  { "cmovl",           Gv, Ev, XX, XX },
+  { "cmovge",          Gv, Ev, XX, XX },
+  { "cmovle",          Gv, Ev, XX, XX },
+  { "cmovg",           Gv, Ev, XX, XX },
   /* 50 */
   /* 50 */
-  { "movmskpX",                Gdq, XS, XX },
+  { "movmskpX",                Gdq, XS, XX, XX },
   { PREGRP13 },
   { PREGRP12 },
   { PREGRP11 },
   { PREGRP13 },
   { PREGRP12 },
   { PREGRP11 },
-  { "andpX",           XM, EX, XX },
-  { "andnpX",          XM, EX, XX },
-  { "orpX",            XM, EX, XX },
-  { "xorpX",           XM, EX, XX },
+  { "andpX",           XM, EX, XX, XX },
+  { "andnpX",          XM, EX, XX, XX },
+  { "orpX",            XM, EX, XX, XX },
+  { "xorpX",           XM, EX, XX, XX },
   /* 58 */
   { PREGRP0 },
   { PREGRP10 },
   /* 58 */
   { PREGRP0 },
   { PREGRP10 },
@@ -893,185 +943,185 @@ static const struct dis386 dis386_twobyte[] = {
   { PREGRP5 },
   { PREGRP6 },
   /* 60 */
   { PREGRP5 },
   { PREGRP6 },
   /* 60 */
-  { "punpcklbw",       MX, EM, XX },
-  { "punpcklwd",       MX, EM, XX },
-  { "punpckldq",       MX, EM, XX },
-  { "packsswb",                MX, EM, XX },
-  { "pcmpgtb",         MX, EM, XX },
-  { "pcmpgtw",         MX, EM, XX },
-  { "pcmpgtd",         MX, EM, XX },
-  { "packuswb",                MX, EM, XX },
+  { "punpcklbw",       MX, EM, XX, XX },
+  { "punpcklwd",       MX, EM, XX, XX },
+  { "punpckldq",       MX, EM, XX, XX },
+  { "packsswb",                MX, EM, XX, XX },
+  { "pcmpgtb",         MX, EM, XX, XX },
+  { "pcmpgtw",         MX, EM, XX, XX },
+  { "pcmpgtd",         MX, EM, XX, XX },
+  { "packuswb",                MX, EM, XX, XX },
   /* 68 */
   /* 68 */
-  { "punpckhbw",       MX, EM, XX },
-  { "punpckhwd",       MX, EM, XX },
-  { "punpckhdq",       MX, EM, XX },
-  { "packssdw",                MX, EM, XX },
+  { "punpckhbw",       MX, EM, XX, XX },
+  { "punpckhwd",       MX, EM, XX, XX },
+  { "punpckhdq",       MX, EM, XX, XX },
+  { "packssdw",                MX, EM, XX, XX },
   { PREGRP26 },
   { PREGRP24 },
   { PREGRP26 },
   { PREGRP24 },
-  { "movd",            MX, Edq, XX },
+  { "movd",            MX, Edq, XX, XX },
   { PREGRP19 },
   /* 70 */
   { PREGRP22 },
   { PREGRP19 },
   /* 70 */
   { PREGRP22 },
-  { GRP10 },
-  { GRP11 },
   { GRP12 },
   { GRP12 },
-  { "pcmpeqb",         MX, EM, XX },
-  { "pcmpeqw",         MX, EM, XX },
-  { "pcmpeqd",         MX, EM, XX },
-  { "emms",            XX, XX, XX },
+  { GRP13 },
+  { GRP14 },
+  { "pcmpeqb",         MX, EM, XX, XX },
+  { "pcmpeqw",         MX, EM, XX, XX },
+  { "pcmpeqd",         MX, EM, XX, XX },
+  { "emms",            XX, XX, XX, XX },
   /* 78 */
   /* 78 */
-  { "vmread",          Em, Gm, XX },
-  { "vmwrite",         Gm, Em, XX },
-  { "(bad)",           XX, XX, XX },
-  { "(bad)",           XX, XX, XX },
+  { PREGRP34 },
+  { PREGRP35 },
+  { "(bad)",           XX, XX, XX, XX },
+  { "(bad)",           XX, XX, XX, XX },
   { PREGRP28 },
   { PREGRP29 },
   { PREGRP23 },
   { PREGRP20 },
   /* 80 */
   { PREGRP28 },
   { PREGRP29 },
   { PREGRP23 },
   { PREGRP20 },
   /* 80 */
-  { "joH",             Jv, XX, cond_jump_flag },
-  { "jnoH",            Jv, XX, cond_jump_flag },
-  { "jbH",             Jv, XX, cond_jump_flag },
-  { "jaeH",            Jv, XX, cond_jump_flag },
-  { "jeH",             Jv, XX, cond_jump_flag },
-  { "jneH",            Jv, XX, cond_jump_flag },
-  { "jbeH",            Jv, XX, cond_jump_flag },
-  { "jaH",             Jv, XX, cond_jump_flag },
+  { "joH",             Jv, XX, cond_jump_flag, XX },
+  { "jnoH",            Jv, XX, cond_jump_flag, XX },
+  { "jbH",             Jv, XX, cond_jump_flag, XX },
+  { "jaeH",            Jv, XX, cond_jump_flag, XX },
+  { "jeH",             Jv, XX, cond_jump_flag, XX },
+  { "jneH",            Jv, XX, cond_jump_flag, XX },
+  { "jbeH",            Jv, XX, cond_jump_flag, XX },
+  { "jaH",             Jv, XX, cond_jump_flag, XX },
   /* 88 */
   /* 88 */
-  { "jsH",             Jv, XX, cond_jump_flag },
-  { "jnsH",            Jv, XX, cond_jump_flag },
-  { "jpH",             Jv, XX, cond_jump_flag },
-  { "jnpH",            Jv, XX, cond_jump_flag },
-  { "jlH",             Jv, XX, cond_jump_flag },
-  { "jgeH",            Jv, XX, cond_jump_flag },
-  { "jleH",            Jv, XX, cond_jump_flag },
-  { "jgH",             Jv, XX, cond_jump_flag },
+  { "jsH",             Jv, XX, cond_jump_flag, XX },
+  { "jnsH",            Jv, XX, cond_jump_flag, XX },
+  { "jpH",             Jv, XX, cond_jump_flag, XX },
+  { "jnpH",            Jv, XX, cond_jump_flag, XX },
+  { "jlH",             Jv, XX, cond_jump_flag, XX },
+  { "jgeH",            Jv, XX, cond_jump_flag, XX },
+  { "jleH",            Jv, XX, cond_jump_flag, XX },
+  { "jgH",             Jv, XX, cond_jump_flag, XX },
   /* 90 */
   /* 90 */
-  { "seto",            Eb, XX, XX },
-  { "setno",           Eb, XX, XX },
-  { "setb",            Eb, XX, XX },
-  { "setae",           Eb, XX, XX },
-  { "sete",            Eb, XX, XX },
-  { "setne",           Eb, XX, XX },
-  { "setbe",           Eb, XX, XX },
-  { "seta",            Eb, XX, XX },
+  { "seto",            Eb, XX, XX, XX },
+  { "setno",           Eb, XX, XX, XX },
+  { "setb",            Eb, XX, XX, XX },
+  { "setae",           Eb, XX, XX, XX },
+  { "sete",            Eb, XX, XX, XX },
+  { "setne",           Eb, XX, XX, XX },
+  { "setbe",           Eb, XX, XX, XX },
+  { "seta",            Eb, XX, XX, XX },
   /* 98 */
   /* 98 */
-  { "sets",            Eb, XX, XX },
-  { "setns",           Eb, XX, XX },
-  { "setp",            Eb, XX, XX },
-  { "setnp",           Eb, XX, XX },
-  { "setl",            Eb, XX, XX },
-  { "setge",           Eb, XX, XX },
-  { "setle",           Eb, XX, XX },
-  { "setg",            Eb, XX, XX },
+  { "sets",            Eb, XX, XX, XX },
+  { "setns",           Eb, XX, XX, XX },
+  { "setp",            Eb, XX, XX, XX },
+  { "setnp",           Eb, XX, XX, XX },
+  { "setl",            Eb, XX, XX, XX },
+  { "setge",           Eb, XX, XX, XX },
+  { "setle",           Eb, XX, XX, XX },
+  { "setg",            Eb, XX, XX, XX },
   /* a0 */
   /* a0 */
-  { "pushT",           fs, XX, XX },
-  { "popT",            fs, XX, XX },
-  { "cpuid",           XX, XX, XX },
-  { "btS",             Ev, Gv, XX },
-  { "shldS",           Ev, Gv, Ib },
-  { "shldS",           Ev, Gv, CL },
+  { "pushT",           fs, XX, XX, XX },
+  { "popT",            fs, XX, XX, XX },
+  { "cpuid",           XX, XX, XX, XX },
+  { "btS",             Ev, Gv, XX, XX },
+  { "shldS",           Ev, Gv, Ib, XX },
+  { "shldS",           Ev, Gv, CL, XX },
   { GRPPADLCK2 },
   { GRPPADLCK1 },
   /* a8 */
   { GRPPADLCK2 },
   { GRPPADLCK1 },
   /* a8 */
-  { "pushT",           gs, XX, XX },
-  { "popT",            gs, XX, XX },
-  { "rsm",             XX, XX, XX },
-  { "btsS",            Ev, Gv, XX },
-  { "shrdS",           Ev, Gv, Ib },
-  { "shrdS",           Ev, Gv, CL },
-  { GRP13 },
-  { "imulS",           Gv, Ev, XX },
+  { "pushT",           gs, XX, XX, XX },
+  { "popT",            gs, XX, XX, XX },
+  { "rsm",             XX, XX, XX, XX },
+  { "btsS",            Ev, Gv, XX, XX },
+  { "shrdS",           Ev, Gv, Ib, XX },
+  { "shrdS",           Ev, Gv, CL, XX },
+  { GRP15 },
+  { "imulS",           Gv, Ev, XX, XX },
   /* b0 */
   /* b0 */
-  { "cmpxchgB",                Eb, Gb, XX },
-  { "cmpxchgS",                Ev, Gv, XX },
-  { "lssS",            Gv, Mp, XX },
-  { "btrS",            Ev, Gv, XX },
-  { "lfsS",            Gv, Mp, XX },
-  { "lgsS",            Gv, Mp, XX },
-  { "movz{bR|x|bR|x}", Gv, Eb, XX },
-  { "movz{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movzww ! */
+  { "cmpxchgB",                Eb, Gb, XX, XX },
+  { "cmpxchgS",                Ev, Gv, XX, XX },
+  { "lssS",            Gv, Mp, XX, XX },
+  { "btrS",            Ev, Gv, XX, XX },
+  { "lfsS",            Gv, Mp, XX, XX },
+  { "lgsS",            Gv, Mp, XX, XX },
+  { "movz{bR|x|bR|x}", Gv, Eb, XX, XX },
+  { "movz{wR|x|wR|x}", Gv, Ew, XX, XX }, /* yes, there really is movzww ! */
   /* b8 */
   /* b8 */
-  { "(bad)",           XX, XX, XX },
-  { "ud2b",            XX, XX, XX },
+  { PREGRP37 },
+  { "ud2b",            XX, XX, XX, XX },
   { GRP8 },
   { GRP8 },
-  { "btcS",            Ev, Gv, XX },
-  { "bsfS",            Gv, Ev, XX },
-  { "bsrS",            Gv, Ev, XX },
-  { "movs{bR|x|bR|x}", Gv, Eb, XX },
-  { "movs{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movsww ! */
+  { "btcS",            Ev, Gv, XX, XX },
+  { "bsfS",            Gv, Ev, XX, XX },
+  { PREGRP36 },
+  { "movs{bR|x|bR|x}", Gv, Eb, XX, XX },
+  { "movs{wR|x|wR|x}", Gv, Ew, XX, XX }, /* yes, there really is movsww ! */
   /* c0 */
   /* c0 */
-  { "xaddB",           Eb, Gb, XX },
-  { "xaddS",           Ev, Gv, XX },
+  { "xaddB",           Eb, Gb, XX, XX },
+  { "xaddS",           Ev, Gv, XX, XX },
   { PREGRP1 },
   { PREGRP1 },
-  { "movntiS",         Ev, Gv, XX },
-  { "pinsrw",          MX, Edqw, Ib },
-  { "pextrw",          Gdq, MS, Ib },
-  { "shufpX",          XM, EX, Ib },
+  { "movntiS",         Ev, Gv, XX, XX },
+  { "pinsrw",          MX, Edqw, Ib, XX },
+  { "pextrw",          Gdq, MS, Ib, XX },
+  { "shufpX",          XM, EX, Ib, XX },
   { GRP9 },
   /* c8 */
   { GRP9 },
   /* c8 */
-  { "bswap",           RMeAX, XX, XX },
-  { "bswap",           RMeCX, XX, XX },
-  { "bswap",           RMeDX, XX, XX },
-  { "bswap",           RMeBX, XX, XX },
-  { "bswap",           RMeSP, XX, XX },
-  { "bswap",           RMeBP, XX, XX },
-  { "bswap",           RMeSI, XX, XX },
-  { "bswap",           RMeDI, XX, XX },
+  { "bswap",           RMeAX, XX, XX, XX },
+  { "bswap",           RMeCX, XX, XX, XX },
+  { "bswap",           RMeDX, XX, XX, XX },
+  { "bswap",           RMeBX, XX, XX, XX },
+  { "bswap",           RMeSP, XX, XX, XX },
+  { "bswap",           RMeBP, XX, XX, XX },
+  { "bswap",           RMeSI, XX, XX, XX },
+  { "bswap",           RMeDI, XX, XX, XX },
   /* d0 */
   { PREGRP27 },
   /* d0 */
   { PREGRP27 },
-  { "psrlw",           MX, EM, XX },
-  { "psrld",           MX, EM, XX },
-  { "psrlq",           MX, EM, XX },
-  { "paddq",           MX, EM, XX },
-  { "pmullw",          MX, EM, XX },
+  { "psrlw",           MX, EM, XX, XX },
+  { "psrld",           MX, EM, XX, XX },
+  { "psrlq",           MX, EM, XX, XX },
+  { "paddq",           MX, EM, XX, XX },
+  { "pmullw",          MX, EM, XX, XX },
   { PREGRP21 },
   { PREGRP21 },
-  { "pmovmskb",                Gdq, MS, XX },
+  { "pmovmskb",                Gdq, MS, XX, XX },
   /* d8 */
   /* d8 */
-  { "psubusb",         MX, EM, XX },
-  { "psubusw",         MX, EM, XX },
-  { "pminub",          MX, EM, XX },
-  { "pand",            MX, EM, XX },
-  { "paddusb",         MX, EM, XX },
-  { "paddusw",         MX, EM, XX },
-  { "pmaxub",          MX, EM, XX },
-  { "pandn",           MX, EM, XX },
+  { "psubusb",         MX, EM, XX, XX },
+  { "psubusw",         MX, EM, XX, XX },
+  { "pminub",          MX, EM, XX, XX },
+  { "pand",            MX, EM, XX, XX },
+  { "paddusb",         MX, EM, XX, XX },
+  { "paddusw",         MX, EM, XX, XX },
+  { "pmaxub",          MX, EM, XX, XX },
+  { "pandn",           MX, EM, XX, XX },
   /* e0 */
   /* e0 */
-  { "pavgb",           MX, EM, XX },
-  { "psraw",           MX, EM, XX },
-  { "psrad",           MX, EM, XX },
-  { "pavgw",           MX, EM, XX },
-  { "pmulhuw",         MX, EM, XX },
-  { "pmulhw",          MX, EM, XX },
+  { "pavgb",           MX, EM, XX, XX },
+  { "psraw",           MX, EM, XX, XX },
+  { "psrad",           MX, EM, XX, XX },
+  { "pavgw",           MX, EM, XX, XX },
+  { "pmulhuw",         MX, EM, XX, XX },
+  { "pmulhw",          MX, EM, XX, XX },
   { PREGRP15 },
   { PREGRP25 },
   /* e8 */
   { PREGRP15 },
   { PREGRP25 },
   /* e8 */
-  { "psubsb",          MX, EM, XX },
-  { "psubsw",          MX, EM, XX },
-  { "pminsw",          MX, EM, XX },
-  { "por",             MX, EM, XX },
-  { "paddsb",          MX, EM, XX },
-  { "paddsw",          MX, EM, XX },
-  { "pmaxsw",          MX, EM, XX },
-  { "pxor",            MX, EM, XX },
+  { "psubsb",          MX, EM, XX, XX },
+  { "psubsw",          MX, EM, XX, XX },
+  { "pminsw",          MX, EM, XX, XX },
+  { "por",             MX, EM, XX, XX },
+  { "paddsb",          MX, EM, XX, XX },
+  { "paddsw",          MX, EM, XX, XX },
+  { "pmaxsw",          MX, EM, XX, XX },
+  { "pxor",            MX, EM, XX, XX },
   /* f0 */
   { PREGRP32 },
   /* f0 */
   { PREGRP32 },
-  { "psllw",           MX, EM, XX },
-  { "pslld",           MX, EM, XX },
-  { "psllq",           MX, EM, XX },
-  { "pmuludq",         MX, EM, XX },
-  { "pmaddwd",         MX, EM, XX },
-  { "psadbw",          MX, EM, XX },
+  { "psllw",           MX, EM, XX, XX },
+  { "pslld",           MX, EM, XX, XX },
+  { "psllq",           MX, EM, XX, XX },
+  { "pmuludq",         MX, EM, XX, XX },
+  { "pmaddwd",         MX, EM, XX, XX },
+  { "psadbw",          MX, EM, XX, XX },
   { PREGRP18 },
   /* f8 */
   { PREGRP18 },
   /* f8 */
-  { "psubb",           MX, EM, XX },
-  { "psubw",           MX, EM, XX },
-  { "psubd",           MX, EM, XX },
-  { "psubq",           MX, EM, XX },
-  { "paddb",           MX, EM, XX },
-  { "paddw",           MX, EM, XX },
-  { "paddd",           MX, EM, XX },
-  { "(bad)",           XX, XX, XX }
+  { "psubb",           MX, EM, XX, XX },
+  { "psubw",           MX, EM, XX, XX },
+  { "psubd",           MX, EM, XX, XX },
+  { "psubq",           MX, EM, XX, XX },
+  { "paddb",           MX, EM, XX, XX },
+  { "paddw",           MX, EM, XX, XX },
+  { "paddd",           MX, EM, XX, XX },
+  { "(bad)",           XX, XX, XX, XX }
 };
 
 static const unsigned char onebyte_has_modrm[256] = {
 };
 
 static const unsigned char onebyte_has_modrm[256] = {
@@ -1101,9 +1151,9 @@ static const unsigned char twobyte_has_modrm[256] = {
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
   /*       -------------------------------        */
   /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
   /*       -------------------------------        */
   /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
-  /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */
+  /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1, /* 1f */
   /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */
   /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */
-  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */
   /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
   /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
   /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
   /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
   /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
   /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
@@ -1111,7 +1161,7 @@ static const unsigned char twobyte_has_modrm[256] = {
   /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
   /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
   /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
   /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
   /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
   /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
-  /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
+  /* b0 */ 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1, /* bf */
   /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
   /* d0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
   /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
   /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
   /* d0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
   /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
@@ -1120,17 +1170,17 @@ static const unsigned char twobyte_has_modrm[256] = {
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
 };
 
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
 };
 
-static const unsigned char twobyte_uses_SSE_prefix[256] = {
+static const unsigned char twobyte_uses_DATA_prefix[256] = {
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
   /*       -------------------------------        */
   /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
   /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
   /*       -------------------------------        */
   /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
   /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */
-  /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */
-  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */
   /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
   /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
   /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
   /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
   /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
   /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
-  /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, /* 7f */
+  /* 70 */ 1,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1, /* 7f */
   /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
   /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
   /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
   /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
   /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
   /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
@@ -1143,6 +1193,196 @@ static const unsigned char twobyte_uses_SSE_prefix[256] = {
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
 };
 
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
 };
 
+static const unsigned char twobyte_uses_REPNZ_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+  /* 10 */ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 0,1,0,0,0,0,0,0,1,1,1,0,1,1,1,1, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+  /* 70 */ 1,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+static const unsigned char twobyte_uses_REPZ_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+  /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, /* 6f */
+  /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, /* bf */
+  /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+/* This is used to determine if opcode 0f 38 XX uses DATA prefix.  */ 
+static const unsigned char threebyte_0x38_uses_DATA_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0, /* 0f */
+  /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+/* This is used to determine if opcode 0f 38 XX uses REPNZ prefix.  */ 
+static const unsigned char threebyte_0x38_uses_REPNZ_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+  /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+/* This is used to determine if opcode 0f 38 XX uses REPZ prefix.  */ 
+static const unsigned char threebyte_0x38_uses_REPZ_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+  /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+/* This is used to determine if opcode 0f 3a XX uses DATA prefix.  */ 
+static const unsigned char threebyte_0x3a_uses_DATA_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, /* 0f */
+  /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+/* This is used to determine if opcode 0f 3a XX uses REPNZ prefix.  */ 
+static const unsigned char threebyte_0x3a_uses_REPNZ_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+  /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+/* This is used to determine if opcode 0f 3a XX uses REPZ prefix.  */ 
+static const unsigned char threebyte_0x3a_uses_REPZ_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+  /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
 static char obuf[100];
 static char *obufp;
 static char scratchbuf[100];
 static char obuf[100];
 static char *obufp;
 static char scratchbuf[100];
@@ -1223,519 +1463,1177 @@ static const char *att_index16[] = {
 static const struct dis386 grps[][8] = {
   /* GRP1b */
   {
 static const struct dis386 grps[][8] = {
   /* GRP1b */
   {
-    { "addA",  Eb, Ib, XX },
-    { "orA",   Eb, Ib, XX },
-    { "adcA",  Eb, Ib, XX },
-    { "sbbA",  Eb, Ib, XX },
-    { "andA",  Eb, Ib, XX },
-    { "subA",  Eb, Ib, XX },
-    { "xorA",  Eb, Ib, XX },
-    { "cmpA",  Eb, Ib, XX }
+    { "addA",  Eb, Ib, XX, XX },
+    { "orA",   Eb, Ib, XX, XX },
+    { "adcA",  Eb, Ib, XX, XX },
+    { "sbbA",  Eb, Ib, XX, XX },
+    { "andA",  Eb, Ib, XX, XX },
+    { "subA",  Eb, Ib, XX, XX },
+    { "xorA",  Eb, Ib, XX, XX },
+    { "cmpA",  Eb, Ib, XX, XX }
   },
   /* GRP1S */
   {
   },
   /* GRP1S */
   {
-    { "addQ",  Ev, Iv, XX },
-    { "orQ",   Ev, Iv, XX },
-    { "adcQ",  Ev, Iv, XX },
-    { "sbbQ",  Ev, Iv, XX },
-    { "andQ",  Ev, Iv, XX },
-    { "subQ",  Ev, Iv, XX },
-    { "xorQ",  Ev, Iv, XX },
-    { "cmpQ",  Ev, Iv, XX }
+    { "addQ",  Ev, Iv, XX, XX },
+    { "orQ",   Ev, Iv, XX, XX },
+    { "adcQ",  Ev, Iv, XX, XX },
+    { "sbbQ",  Ev, Iv, XX, XX },
+    { "andQ",  Ev, Iv, XX, XX },
+    { "subQ",  Ev, Iv, XX, XX },
+    { "xorQ",  Ev, Iv, XX, XX },
+    { "cmpQ",  Ev, Iv, XX, XX }
   },
   /* GRP1Ss */
   {
   },
   /* GRP1Ss */
   {
-    { "addQ",  Ev, sIb, XX },
-    { "orQ",   Ev, sIb, XX },
-    { "adcQ",  Ev, sIb, XX },
-    { "sbbQ",  Ev, sIb, XX },
-    { "andQ",  Ev, sIb, XX },
-    { "subQ",  Ev, sIb, XX },
-    { "xorQ",  Ev, sIb, XX },
-    { "cmpQ",  Ev, sIb, XX }
+    { "addQ",  Ev, sIb, XX, XX },
+    { "orQ",   Ev, sIb, XX, XX },
+    { "adcQ",  Ev, sIb, XX, XX },
+    { "sbbQ",  Ev, sIb, XX, XX },
+    { "andQ",  Ev, sIb, XX, XX },
+    { "subQ",  Ev, sIb, XX, XX },
+    { "xorQ",  Ev, sIb, XX, XX },
+    { "cmpQ",  Ev, sIb, XX, XX }
   },
   /* GRP2b */
   {
   },
   /* GRP2b */
   {
-    { "rolA",  Eb, Ib, XX },
-    { "rorA",  Eb, Ib, XX },
-    { "rclA",  Eb, Ib, XX },
-    { "rcrA",  Eb, Ib, XX },
-    { "shlA",  Eb, Ib, XX },
-    { "shrA",  Eb, Ib, XX },
-    { "(bad)", XX, XX, XX },
-    { "sarA",  Eb, Ib, XX },
+    { "rolA",  Eb, Ib, XX, XX },
+    { "rorA",  Eb, Ib, XX, XX },
+    { "rclA",  Eb, Ib, XX, XX },
+    { "rcrA",  Eb, Ib, XX, XX },
+    { "shlA",  Eb, Ib, XX, XX },
+    { "shrA",  Eb, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "sarA",  Eb, Ib, XX, XX },
   },
   /* GRP2S */
   {
   },
   /* GRP2S */
   {
-    { "rolQ",  Ev, Ib, XX },
-    { "rorQ",  Ev, Ib, XX },
-    { "rclQ",  Ev, Ib, XX },
-    { "rcrQ",  Ev, Ib, XX },
-    { "shlQ",  Ev, Ib, XX },
-    { "shrQ",  Ev, Ib, XX },
-    { "(bad)", XX, XX, XX },
-    { "sarQ",  Ev, Ib, XX },
+    { "rolQ",  Ev, Ib, XX, XX },
+    { "rorQ",  Ev, Ib, XX, XX },
+    { "rclQ",  Ev, Ib, XX, XX },
+    { "rcrQ",  Ev, Ib, XX, XX },
+    { "shlQ",  Ev, Ib, XX, XX },
+    { "shrQ",  Ev, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "sarQ",  Ev, Ib, XX, XX },
   },
   /* GRP2b_one */
   {
   },
   /* GRP2b_one */
   {
-    { "rolA",  Eb, I1, XX },
-    { "rorA",  Eb, I1, XX },
-    { "rclA",  Eb, I1, XX },
-    { "rcrA",  Eb, I1, XX },
-    { "shlA",  Eb, I1, XX },
-    { "shrA",  Eb, I1, XX },
-    { "(bad)", XX, XX, XX },
-    { "sarA",  Eb, I1, XX },
+    { "rolA",  Eb, I1, XX, XX },
+    { "rorA",  Eb, I1, XX, XX },
+    { "rclA",  Eb, I1, XX, XX },
+    { "rcrA",  Eb, I1, XX, XX },
+    { "shlA",  Eb, I1, XX, XX },
+    { "shrA",  Eb, I1, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "sarA",  Eb, I1, XX, XX },
   },
   /* GRP2S_one */
   {
   },
   /* GRP2S_one */
   {
-    { "rolQ",  Ev, I1, XX },
-    { "rorQ",  Ev, I1, XX },
-    { "rclQ",  Ev, I1, XX },
-    { "rcrQ",  Ev, I1, XX },
-    { "shlQ",  Ev, I1, XX },
-    { "shrQ",  Ev, I1, XX },
-    { "(bad)", XX, XX, XX},
-    { "sarQ",  Ev, I1, XX },
+    { "rolQ",  Ev, I1, XX, XX },
+    { "rorQ",  Ev, I1, XX, XX },
+    { "rclQ",  Ev, I1, XX, XX },
+    { "rcrQ",  Ev, I1, XX, XX },
+    { "shlQ",  Ev, I1, XX, XX },
+    { "shrQ",  Ev, I1, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "sarQ",  Ev, I1, XX, XX },
   },
   /* GRP2b_cl */
   {
   },
   /* GRP2b_cl */
   {
-    { "rolA",  Eb, CL, XX },
-    { "rorA",  Eb, CL, XX },
-    { "rclA",  Eb, CL, XX },
-    { "rcrA",  Eb, CL, XX },
-    { "shlA",  Eb, CL, XX },
-    { "shrA",  Eb, CL, XX },
-    { "(bad)", XX, XX, XX },
-    { "sarA",  Eb, CL, XX },
+    { "rolA",  Eb, CL, XX, XX },
+    { "rorA",  Eb, CL, XX, XX },
+    { "rclA",  Eb, CL, XX, XX },
+    { "rcrA",  Eb, CL, XX, XX },
+    { "shlA",  Eb, CL, XX, XX },
+    { "shrA",  Eb, CL, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "sarA",  Eb, CL, XX, XX },
   },
   /* GRP2S_cl */
   {
   },
   /* GRP2S_cl */
   {
-    { "rolQ",  Ev, CL, XX },
-    { "rorQ",  Ev, CL, XX },
-    { "rclQ",  Ev, CL, XX },
-    { "rcrQ",  Ev, CL, XX },
-    { "shlQ",  Ev, CL, XX },
-    { "shrQ",  Ev, CL, XX },
-    { "(bad)", XX, XX, XX },
-    { "sarQ",  Ev, CL, XX }
+    { "rolQ",  Ev, CL, XX, XX },
+    { "rorQ",  Ev, CL, XX, XX },
+    { "rclQ",  Ev, CL, XX, XX },
+    { "rcrQ",  Ev, CL, XX, XX },
+    { "shlQ",  Ev, CL, XX, XX },
+    { "shrQ",  Ev, CL, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "sarQ",  Ev, CL, XX, XX }
   },
   /* GRP3b */
   {
   },
   /* GRP3b */
   {
-    { "testA", Eb, Ib, XX },
-    { "(bad)", Eb, XX, XX },
-    { "notA",  Eb, XX, XX },
-    { "negA",  Eb, XX, XX },
-    { "mulA",  Eb, XX, XX },   /* Don't print the implicit %al register,  */
-    { "imulA", Eb, XX, XX },   /* to distinguish these opcodes from other */
-    { "divA",  Eb, XX, XX },   /* mul/imul opcodes.  Do the same for div  */
-    { "idivA", Eb, XX, XX }    /* and idiv for consistency.               */
+    { "testA", Eb, Ib, XX, XX },
+    { "(bad)", Eb, XX, XX, XX },
+    { "notA",  Eb, XX, XX, XX },
+    { "negA",  Eb, XX, XX, XX },
+    { "mulA",  Eb, XX, XX, XX },       /* Don't print the implicit %al register,  */
+    { "imulA", Eb, XX, XX, XX },       /* to distinguish these opcodes from other */
+    { "divA",  Eb, XX, XX, XX },       /* mul/imul opcodes.  Do the same for div  */
+    { "idivA", Eb, XX, XX, XX }        /* and idiv for consistency.               */
   },
   /* GRP3S */
   {
   },
   /* GRP3S */
   {
-    { "testQ", Ev, Iv, XX },
-    { "(bad)", XX, XX, XX },
-    { "notQ",  Ev, XX, XX },
-    { "negQ",  Ev, XX, XX },
-    { "mulQ",  Ev, XX, XX },   /* Don't print the implicit register.  */
-    { "imulQ", Ev, XX, XX },
-    { "divQ",  Ev, XX, XX },
-    { "idivQ", Ev, XX, XX },
+    { "testQ", Ev, Iv, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "notQ",  Ev, XX, XX, XX },
+    { "negQ",  Ev, XX, XX, XX },
+    { "mulQ",  Ev, XX, XX, XX },       /* Don't print the implicit register.  */
+    { "imulQ", Ev, XX, XX, XX },
+    { "divQ",  Ev, XX, XX, XX },
+    { "idivQ", Ev, XX, XX, XX },
   },
   /* GRP4 */
   {
   },
   /* GRP4 */
   {
-    { "incA",  Eb, XX, XX },
-    { "decA",  Eb, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
+    { "incA",  Eb, XX, XX, XX },
+    { "decA",  Eb, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* GRP5 */
   {
   },
   /* GRP5 */
   {
-    { "incQ",  Ev, XX, XX },
-    { "decQ",  Ev, XX, XX },
-    { "callT", indirEv, XX, XX },
-    { "JcallT",        indirEp, XX, XX },
-    { "jmpT",  indirEv, XX, XX },
-    { "JjmpT", indirEp, XX, XX },
-    { "pushU", Ev, XX, XX },
-    { "(bad)", XX, XX, XX },
+    { "incQ",  Ev, XX, XX, XX },
+    { "decQ",  Ev, XX, XX, XX },
+    { "callT", indirEv, XX, XX, XX },
+    { "JcallT",        indirEp, XX, XX, XX },
+    { "jmpT",  indirEv, XX, XX, XX },
+    { "JjmpT", indirEp, XX, XX, XX },
+    { "pushU", stackEv, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* GRP6 */
   {
   },
   /* GRP6 */
   {
-    { "sldtQ", Ev, XX, XX },
-    { "strQ",  Ev, XX, XX },
-    { "lldt",  Ew, XX, XX },
-    { "ltr",   Ew, XX, XX },
-    { "verr",  Ew, XX, XX },
-    { "verw",  Ew, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX }
+    { "sldtD", Sv, XX, XX, XX },
+    { "strD",  Sv, XX, XX, XX },
+    { "lldt",  Ew, XX, XX, XX },
+    { "ltr",   Ew, XX, XX, XX },
+    { "verr",  Ew, XX, XX, XX },
+    { "verw",  Ew, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX }
   },
   /* GRP7 */
   {
   },
   /* GRP7 */
   {
-    { "sgdtIQ", VMX_Fixup, 0, XX, XX },
-    { "sidtIQ", PNI_Fixup, 0, XX, XX },
-    { "lgdt{Q|Q||}",    M, XX, XX },
-    { "lidt{Q|Q||}",    SVME_Fixup, 0, XX, XX },
-    { "smswQ", Ev, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "lmsw",  Ew, XX, XX },
-    { "invlpg",        INVLPG_Fixup, w_mode, XX, XX },
+    { "sgdt{Q|IQ||}", VMX_Fixup, 0, XX, XX, XX },
+    { "sidt{Q|IQ||}", PNI_Fixup, 0, XX, XX, XX },
+    { "lgdt{Q|Q||}",    M, XX, XX, XX },
+    { "lidt{Q|Q||}",    SVME_Fixup, 0, XX, XX, XX },
+    { "smswD", Sv, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "lmsw",  Ew, XX, XX, XX },
+    { "invlpg",        INVLPG_Fixup, w_mode, XX, XX, XX },
   },
   /* GRP8 */
   {
   },
   /* GRP8 */
   {
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "btQ",   Ev, Ib, XX },
-    { "btsQ",  Ev, Ib, XX },
-    { "btrQ",  Ev, Ib, XX },
-    { "btcQ",  Ev, Ib, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "btQ",   Ev, Ib, XX, XX },
+    { "btsQ",  Ev, Ib, XX, XX },
+    { "btrQ",  Ev, Ib, XX, XX },
+    { "btcQ",  Ev, Ib, XX, XX },
   },
   /* GRP9 */
   {
   },
   /* GRP9 */
   {
-    { "(bad)", XX, XX, XX },
-    { "cmpxchg8b", Eq, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "",      VM, XX, XX },           /* See OP_VMX.  */
-    { "vmptrst", Eq, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "cmpxchg8b", CMPXCHG8B_Fixup, q_mode, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "",      VM, XX, XX, XX },               /* See OP_VMX.  */
+    { "vmptrst", Mq, XX, XX, XX },
   },
   },
-  /* GRP10 */
+  /* GRP11_C6 */
   {
   {
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "psrlw", MS, Ib, XX },
-    { "(bad)", XX, XX, XX },
-    { "psraw", MS, Ib, XX },
-    { "(bad)", XX, XX, XX },
-    { "psllw", MS, Ib, XX },
-    { "(bad)", XX, XX, XX },
+    { "movA",  Eb, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   },
-  /* GRP11 */
+  /* GRP11_C7 */
   {
   {
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "psrld", MS, Ib, XX },
-    { "(bad)", XX, XX, XX },
-    { "psrad", MS, Ib, XX },
-    { "(bad)", XX, XX, XX },
-    { "pslld", MS, Ib, XX },
-    { "(bad)", XX, XX, XX },
+    { "movQ",  Ev, Iv, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* GRP12 */
   {
   },
   /* GRP12 */
   {
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "psrlq", MS, Ib, XX },
-    { "psrldq",        MS, Ib, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "psllq", MS, Ib, XX },
-    { "pslldq",        MS, Ib, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "psrlw", MS, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "psraw", MS, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "psllw", MS, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* GRP13 */
   {
   },
   /* GRP13 */
   {
-    { "fxsave", Ev, XX, XX },
-    { "fxrstor", Ev, XX, XX },
-    { "ldmxcsr", Ev, XX, XX },
-    { "stmxcsr", Ev, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "lfence", OP_0fae, 0, XX, XX },
-    { "mfence", OP_0fae, 0, XX, XX },
-    { "clflush", OP_0fae, 0, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "psrld", MS, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "psrad", MS, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "pslld", MS, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* GRP14 */
   {
   },
   /* GRP14 */
   {
-    { "prefetchnta", Ev, XX, XX },
-    { "prefetcht0", Ev, XX, XX },
-    { "prefetcht1", Ev, XX, XX },
-    { "prefetcht2", Ev, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "psrlq", MS, Ib, XX, XX },
+    { "psrldq",        MS, Ib, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "psllq", MS, Ib, XX, XX },
+    { "pslldq",        MS, Ib, XX, XX },
+  },
+  /* GRP15 */
+  {
+    { "fxsave", Ev, XX, XX, XX },
+    { "fxrstor", Ev, XX, XX, XX },
+    { "ldmxcsr", Ev, XX, XX, XX },
+    { "stmxcsr", Ev, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "lfence", OP_0fae, 0, XX, XX, XX },
+    { "mfence", OP_0fae, 0, XX, XX, XX },
+    { "clflush", OP_0fae, 0, XX, XX, XX },
+  },
+  /* GRP16 */
+  {
+    { "prefetchnta", Ev, XX, XX, XX },
+    { "prefetcht0", Ev, XX, XX, XX },
+    { "prefetcht1", Ev, XX, XX, XX },
+    { "prefetcht2", Ev, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* GRPAMD */
   {
   },
   /* GRPAMD */
   {
-    { "prefetch", Eb, XX, XX },
-    { "prefetchw", Eb, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
+    { "prefetch", Eb, XX, XX, XX },
+    { "prefetchw", Eb, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* GRPPADLCK1 */
   {
   },
   /* GRPPADLCK1 */
   {
-    { "xstore-rng", OP_0f07, 0, XX, XX },
-    { "xcrypt-ecb", OP_0f07, 0, XX, XX },
-    { "xcrypt-cbc", OP_0f07, 0, XX, XX },
-    { "xcrypt-ctr", OP_0f07, 0, XX, XX },
-    { "xcrypt-cfb", OP_0f07, 0, XX, XX },
-    { "xcrypt-ofb", OP_0f07, 0, XX, XX },
-    { "(bad)", OP_0f07, 0, XX, XX },
-    { "(bad)", OP_0f07, 0, XX, XX },
+    { "xstore-rng", OP_0f07, 0, XX, XX, XX },
+    { "xcrypt-ecb", OP_0f07, 0, XX, XX, XX },
+    { "xcrypt-cbc", OP_0f07, 0, XX, XX, XX },
+    { "xcrypt-ctr", OP_0f07, 0, XX, XX, XX },
+    { "xcrypt-cfb", OP_0f07, 0, XX, XX, XX },
+    { "xcrypt-ofb", OP_0f07, 0, XX, XX, XX },
+    { "(bad)", OP_0f07, 0, XX, XX, XX },
+    { "(bad)", OP_0f07, 0, XX, XX, XX },
   },
   /* GRPPADLCK2 */
   {
   },
   /* GRPPADLCK2 */
   {
-    { "montmul", OP_0f07, 0, XX, XX },
-    { "xsha1",   OP_0f07, 0, XX, XX },
-    { "xsha256", OP_0f07, 0, XX, XX },
-    { "(bad)",  OP_0f07, 0, XX, XX },
-    { "(bad)",   OP_0f07, 0, XX, XX },
-    { "(bad)",   OP_0f07, 0, XX, XX },
-    { "(bad)",  OP_0f07, 0, XX, XX },
-    { "(bad)",  OP_0f07, 0, XX, XX },
+    { "montmul", OP_0f07, 0, XX, XX, XX },
+    { "xsha1",   OP_0f07, 0, XX, XX, XX },
+    { "xsha256", OP_0f07, 0, XX, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX, XX },
+    { "(bad)",   OP_0f07, 0, XX, XX, XX },
+    { "(bad)",   OP_0f07, 0, XX, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX, XX },
   }
 };
 
 static const struct dis386 prefix_user_table[][4] = {
   /* PREGRP0 */
   {
   }
 };
 
 static const struct dis386 prefix_user_table[][4] = {
   /* PREGRP0 */
   {
-    { "addps", XM, EX, XX },
-    { "addss", XM, EX, XX },
-    { "addpd", XM, EX, XX },
-    { "addsd", XM, EX, XX },
+    { "addps", XM, EX, XX, XX },
+    { "addss", XM, EX, XX, XX },
+    { "addpd", XM, EX, XX, XX },
+    { "addsd", XM, EX, XX, XX },
   },
   /* PREGRP1 */
   {
   },
   /* PREGRP1 */
   {
-    { "", XM, EX, OPSIMD },    /* See OP_SIMD_SUFFIX.  */
-    { "", XM, EX, OPSIMD },
-    { "", XM, EX, OPSIMD },
-    { "", XM, EX, OPSIMD },
+    { "", XM, EX, OPSIMD, XX },        /* See OP_SIMD_SUFFIX.  */
+    { "", XM, EX, OPSIMD, XX },
+    { "", XM, EX, OPSIMD, XX },
+    { "", XM, EX, OPSIMD, XX },
   },
   /* PREGRP2 */
   {
   },
   /* PREGRP2 */
   {
-    { "cvtpi2ps", XM, EM, XX },
-    { "cvtsi2ssY", XM, Ev, XX },
-    { "cvtpi2pd", XM, EM, XX },
-    { "cvtsi2sdY", XM, Ev, XX },
+    { "cvtpi2ps", XM, EMC, XX, XX },
+    { "cvtsi2ssY", XM, Ev, XX, XX },
+    { "cvtpi2pd", XM, EMC, XX, XX },
+    { "cvtsi2sdY", XM, Ev, XX, XX },
   },
   /* PREGRP3 */
   {
   },
   /* PREGRP3 */
   {
-    { "cvtps2pi", MX, EX, XX },
-    { "cvtss2siY", Gv, EX, XX },
-    { "cvtpd2pi", MX, EX, XX },
-    { "cvtsd2siY", Gv, EX, XX },
+    { "cvtps2pi", MXC, EX, XX, XX },
+    { "cvtss2siY", Gv, EX, XX, XX },
+    { "cvtpd2pi", MXC, EX, XX, XX },
+    { "cvtsd2siY", Gv, EX, XX, XX },
   },
   /* PREGRP4 */
   {
   },
   /* PREGRP4 */
   {
-    { "cvttps2pi", MX, EX, XX },
-    { "cvttss2siY", Gv, EX, XX },
-    { "cvttpd2pi", MX, EX, XX },
-    { "cvttsd2siY", Gv, EX, XX },
+    { "cvttps2pi", MXC, EX, XX, XX },
+    { "cvttss2siY", Gv, EX, XX, XX },
+    { "cvttpd2pi", MXC, EX, XX, XX },
+    { "cvttsd2siY", Gv, EX, XX, XX },
   },
   /* PREGRP5 */
   {
   },
   /* PREGRP5 */
   {
-    { "divps", XM, EX, XX },
-    { "divss", XM, EX, XX },
-    { "divpd", XM, EX, XX },
-    { "divsd", XM, EX, XX },
+    { "divps", XM, EX, XX, XX },
+    { "divss", XM, EX, XX, XX },
+    { "divpd", XM, EX, XX, XX },
+    { "divsd", XM, EX, XX, XX },
   },
   /* PREGRP6 */
   {
   },
   /* PREGRP6 */
   {
-    { "maxps", XM, EX, XX },
-    { "maxss", XM, EX, XX },
-    { "maxpd", XM, EX, XX },
-    { "maxsd", XM, EX, XX },
+    { "maxps", XM, EX, XX, XX },
+    { "maxss", XM, EX, XX, XX },
+    { "maxpd", XM, EX, XX, XX },
+    { "maxsd", XM, EX, XX, XX },
   },
   /* PREGRP7 */
   {
   },
   /* PREGRP7 */
   {
-    { "minps", XM, EX, XX },
-    { "minss", XM, EX, XX },
-    { "minpd", XM, EX, XX },
-    { "minsd", XM, EX, XX },
+    { "minps", XM, EX, XX, XX },
+    { "minss", XM, EX, XX, XX },
+    { "minpd", XM, EX, XX, XX },
+    { "minsd", XM, EX, XX, XX },
   },
   /* PREGRP8 */
   {
   },
   /* PREGRP8 */
   {
-    { "movups", XM, EX, XX },
-    { "movss", XM, EX, XX },
-    { "movupd", XM, EX, XX },
-    { "movsd", XM, EX, XX },
+    { "movups", XM, EX, XX, XX },
+    { "movss", XM, EX, XX, XX },
+    { "movupd", XM, EX, XX, XX },
+    { "movsd", XM, EX, XX, XX },
   },
   /* PREGRP9 */
   {
   },
   /* PREGRP9 */
   {
-    { "movups", EX, XM, XX },
-    { "movss", EX, XM, XX },
-    { "movupd", EX, XM, XX },
-    { "movsd", EX, XM, XX },
+    { "movups", EX, XM, XX, XX },
+    { "movss", EX, XM, XX, XX },
+    { "movupd", EX, XM, XX, XX },
+    { "movsd", EX, XM, XX, XX },
   },
   /* PREGRP10 */
   {
   },
   /* PREGRP10 */
   {
-    { "mulps", XM, EX, XX },
-    { "mulss", XM, EX, XX },
-    { "mulpd", XM, EX, XX },
-    { "mulsd", XM, EX, XX },
+    { "mulps", XM, EX, XX, XX },
+    { "mulss", XM, EX, XX, XX },
+    { "mulpd", XM, EX, XX, XX },
+    { "mulsd", XM, EX, XX, XX },
   },
   /* PREGRP11 */
   {
   },
   /* PREGRP11 */
   {
-    { "rcpps", XM, EX, XX },
-    { "rcpss", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
+    { "rcpps", XM, EX, XX, XX },
+    { "rcpss", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
   },
   /* PREGRP12 */
   {
   },
   /* PREGRP12 */
   {
-    { "rsqrtps", XM, EX, XX },
-    { "rsqrtss", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
+    { "rsqrtps", XM, EX, XX, XX },
+    { "rsqrtss", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
   },
   /* PREGRP13 */
   {
   },
   /* PREGRP13 */
   {
-    { "sqrtps", XM, EX, XX },
-    { "sqrtss", XM, EX, XX },
-    { "sqrtpd", XM, EX, XX },
-    { "sqrtsd", XM, EX, XX },
+    { "sqrtps", XM, EX, XX, XX },
+    { "sqrtss", XM, EX, XX, XX },
+    { "sqrtpd", XM, EX, XX, XX },
+    { "sqrtsd", XM, EX, XX, XX },
   },
   /* PREGRP14 */
   {
   },
   /* PREGRP14 */
   {
-    { "subps", XM, EX, XX },
-    { "subss", XM, EX, XX },
-    { "subpd", XM, EX, XX },
-    { "subsd", XM, EX, XX },
+    { "subps", XM, EX, XX, XX },
+    { "subss", XM, EX, XX, XX },
+    { "subpd", XM, EX, XX, XX },
+    { "subsd", XM, EX, XX, XX },
   },
   /* PREGRP15 */
   {
   },
   /* PREGRP15 */
   {
-    { "(bad)", XM, EX, XX },
-    { "cvtdq2pd", XM, EX, XX },
-    { "cvttpd2dq", XM, EX, XX },
-    { "cvtpd2dq", XM, EX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "cvtdq2pd", XM, EX, XX, XX },
+    { "cvttpd2dq", XM, EX, XX, XX },
+    { "cvtpd2dq", XM, EX, XX, XX },
   },
   /* PREGRP16 */
   {
   },
   /* PREGRP16 */
   {
-    { "cvtdq2ps", XM, EX, XX },
-    { "cvttps2dq",XM, EX, XX },
-    { "cvtps2dq",XM, EX, XX },
-    { "(bad)", XM, EX, XX },
+    { "cvtdq2ps", XM, EX, XX, XX },
+    { "cvttps2dq",XM, EX, XX, XX },
+    { "cvtps2dq",XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
   },
   /* PREGRP17 */
   {
   },
   /* PREGRP17 */
   {
-    { "cvtps2pd", XM, EX, XX },
-    { "cvtss2sd", XM, EX, XX },
-    { "cvtpd2ps", XM, EX, XX },
-    { "cvtsd2ss", XM, EX, XX },
+    { "cvtps2pd", XM, EX, XX, XX },
+    { "cvtss2sd", XM, EX, XX, XX },
+    { "cvtpd2ps", XM, EX, XX, XX },
+    { "cvtsd2ss", XM, EX, XX, XX },
   },
   /* PREGRP18 */
   {
   },
   /* PREGRP18 */
   {
-    { "maskmovq", MX, MS, XX },
-    { "(bad)", XM, EX, XX },
-    { "maskmovdqu", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
+    { "maskmovq", MX, MS, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "maskmovdqu", XM, XS, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
   },
   /* PREGRP19 */
   {
   },
   /* PREGRP19 */
   {
-    { "movq", MX, EM, XX },
-    { "movdqu", XM, EX, XX },
-    { "movdqa", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
+    { "movq", MX, EM, XX, XX },
+    { "movdqu", XM, EX, XX, XX },
+    { "movdqa", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
   },
   /* PREGRP20 */
   {
   },
   /* PREGRP20 */
   {
-    { "movq", EM, MX, XX },
-    { "movdqu", EX, XM, XX },
-    { "movdqa", EX, XM, XX },
-    { "(bad)", EX, XM, XX },
+    { "movq", EM, MX, XX, XX },
+    { "movdqu", EX, XM, XX, XX },
+    { "movdqa", EX, XM, XX, XX },
+    { "(bad)", EX, XM, XX, XX },
   },
   /* PREGRP21 */
   {
   },
   /* PREGRP21 */
   {
-    { "(bad)", EX, XM, XX },
-    { "movq2dq", XM, MS, XX },
-    { "movq", EX, XM, XX },
-    { "movdq2q", MX, XS, XX },
+    { "(bad)", EX, XM, XX, XX },
+    { "movq2dq", XM, MS, XX, XX },
+    { "movq", EX, XM, XX, XX },
+    { "movdq2q", MX, XS, XX, XX },
   },
   /* PREGRP22 */
   {
   },
   /* PREGRP22 */
   {
-    { "pshufw", MX, EM, Ib },
-    { "pshufhw", XM, EX, Ib },
-    { "pshufd", XM, EX, Ib },
-    { "pshuflw", XM, EX, Ib },
+    { "pshufw", MX, EM, Ib, XX },
+    { "pshufhw", XM, EX, Ib, XX },
+    { "pshufd", XM, EX, Ib, XX },
+    { "pshuflw", XM, EX, Ib, XX },
   },
   /* PREGRP23 */
   {
   },
   /* PREGRP23 */
   {
-    { "movd", Edq, MX, XX },
-    { "movq", XM, EX, XX },
-    { "movd", Edq, XM, XX },
-    { "(bad)", Ed, XM, XX },
+    { "movd", Edq, MX, XX, XX },
+    { "movq", XM, EX, XX, XX },
+    { "movd", Edq, XM, XX, XX },
+    { "(bad)", Ed, XM, XX, XX },
   },
   /* PREGRP24 */
   {
   },
   /* PREGRP24 */
   {
-    { "(bad)", MX, EX, XX },
-    { "(bad)", XM, EX, XX },
-    { "punpckhqdq", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
+    { "(bad)", MX, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "punpckhqdq", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
   },
   /* PREGRP25 */
   {
   },
   /* PREGRP25 */
   {
-    { "movntq", EM, MX, XX },
-    { "(bad)", EM, XM, XX },
-    { "movntdq", EM, XM, XX },
-    { "(bad)", EM, XM, XX },
+    { "movntq", EM, MX, XX, XX },
+    { "(bad)", EM, XM, XX, XX },
+    { "movntdq", EM, XM, XX, XX },
+    { "(bad)", EM, XM, XX, XX },
   },
   /* PREGRP26 */
   {
   },
   /* PREGRP26 */
   {
-    { "(bad)", MX, EX, XX },
-    { "(bad)", XM, EX, XX },
-    { "punpcklqdq", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
+    { "(bad)", MX, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "punpcklqdq", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
   },
   /* PREGRP27 */
   {
   },
   /* PREGRP27 */
   {
-    { "(bad)", MX, EX, XX },
-    { "(bad)", XM, EX, XX },
-    { "addsubpd", XM, EX, XX },
-    { "addsubps", XM, EX, XX },
+    { "(bad)", MX, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "addsubpd", XM, EX, XX, XX },
+    { "addsubps", XM, EX, XX, XX },
   },
   /* PREGRP28 */
   {
   },
   /* PREGRP28 */
   {
-    { "(bad)", MX, EX, XX },
-    { "(bad)", XM, EX, XX },
-    { "haddpd", XM, EX, XX },
-    { "haddps", XM, EX, XX },
+    { "(bad)", MX, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "haddpd", XM, EX, XX, XX },
+    { "haddps", XM, EX, XX, XX },
   },
   /* PREGRP29 */
   {
   },
   /* PREGRP29 */
   {
-    { "(bad)", MX, EX, XX },
-    { "(bad)", XM, EX, XX },
-    { "hsubpd", XM, EX, XX },
-    { "hsubps", XM, EX, XX },
+    { "(bad)", MX, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "hsubpd", XM, EX, XX, XX },
+    { "hsubps", XM, EX, XX, XX },
   },
   /* PREGRP30 */
   {
   },
   /* PREGRP30 */
   {
-    { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
-    { "movsldup", XM, EX, XX },
-    { "movlpd", XM, EX, XX },
-    { "movddup", XM, EX, XX },
+    { "movlpX", XM, EX, SIMD_Fixup, 'h', XX }, /* really only 2 operands */
+    { "movsldup", XM, EX, XX, XX },
+    { "movlpd", XM, EX, XX, XX },
+    { "movddup", XM, EX, XX, XX },
   },
   /* PREGRP31 */
   {
   },
   /* PREGRP31 */
   {
-    { "movhpX", XM, EX, SIMD_Fixup, 'l' },
-    { "movshdup", XM, EX, XX },
-    { "movhpd", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
+    { "movhpX", XM, EX, SIMD_Fixup, 'l', XX },
+    { "movshdup", XM, EX, XX, XX },
+    { "movhpd", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
   },
   /* PREGRP32 */
   {
   },
   /* PREGRP32 */
   {
-    { "(bad)", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
-    { "(bad)", XM, EX, XX },
-    { "lddqu", XM, M, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "(bad)", XM, EX, XX, XX },
+    { "lddqu", XM, M, XX, XX },
+  },
+  /* PREGRP33 */
+  {
+    {"movntps",Ev, XM, XX, XX },
+    {"movntss",Ev, XM, XX, XX },
+    {"movntpd",Ev, XM, XX, XX },
+    {"movntsd",Ev, XM, XX, XX },
+  },
+
+  /* PREGRP34 */
+  {
+    {"vmread", Em, Gm, XX, XX },
+    {"(bad)",  XX, XX, XX, XX },
+    {"extrq",  XS, Ib, Ib, XX },
+    {"insertq",XM, XS, Ib, Ib },
+  },
+  
+ /* PREGRP35 */  
+  {
+    {"vmwrite", Gm, Em, XX, XX },
+    {"(bad)",   XX, XX, XX, XX },
+    {"extrq",   XM, XS, XX, XX },
+    {"insertq", XM, XS, XX, XX },
+  }, 
+
+  /* PREGRP36 */
+  {
+    { "bsrS",   Gv, Ev, XX, XX },
+    { "lzcntS", Gv, Ev, XX, XX },
+    { "bsrS",  Gv, Ev, XX, XX },
+    { "(bad)",  XX, XX, XX, XX },
+  },
+
+  /* PREGRP37 */
+  {
+    { "(bad)",  XX, XX, XX, XX },
+    { "popcntS",Gv, Ev, XX, XX },
+    { "(bad)",  XX, XX, XX, XX },
+    { "(bad)",  XX, XX, XX, XX },    
   },
 };
 
 static const struct dis386 x86_64_table[][2] = {
   {
   },
 };
 
 static const struct dis386 x86_64_table[][2] = {
   {
-    { "arpl", Ew, Gw, XX },
-    { "movs{||lq|xd}", Gv, Ed, XX },
+    { "pusha{P|}",     XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+  },
+  {
+    { "popa{P|}",      XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+  },
+  {
+    { "bound{S|}",     Gv, Ma, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+  },
+  {
+    { "arpl",          Ew, Gw, XX, XX },
+    { "movs{||lq|xd}", Gv, Ed, XX, XX },
+  },
+};
+
+static const struct dis386 three_byte_table[][256] = {
+  /* THREE_BYTE_0 */
+  {
+    /* 00 */
+    { "pshufb",                MX, EM, XX, XX },
+    { "phaddw",                MX, EM, XX, XX },
+    { "phaddd",                MX, EM, XX, XX },
+    { "phaddsw",       MX, EM, XX, XX },
+    { "pmaddubsw",     MX, EM, XX, XX },
+    { "phsubw",                MX, EM, XX, XX },
+    { "phsubd",                MX, EM, XX, XX },
+    { "phsubsw",       MX, EM, XX, XX },
+    /* 08 */
+    { "psignb",                MX, EM, XX, XX },
+    { "psignw",                MX, EM, XX, XX },
+    { "psignd",                MX, EM, XX, XX },
+    { "pmulhrsw",      MX, EM, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 10 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 18 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "pabsb",         MX, EM, XX, XX },
+    { "pabsw",         MX, EM, XX, XX },
+    { "pabsd",         MX, EM, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 20 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 28 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 30 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 38 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 40 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 48 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 50 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 58 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 60 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 68 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 70 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 78 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 80 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 88 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 90 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 98 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* a0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* a8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* b0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* b8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* c0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* c8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* d0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* d8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* e0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* e8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* f0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* f8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX }
+  },
+  /* THREE_BYTE_1 */
+  {
+    /* 00 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 08 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "palignr",       MX, EM, Ib, XX },
+    /* 10 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 18 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 20 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 28 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 30 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 38 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 40 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 48 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 50 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 58 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 60 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 68 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 70 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 78 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 80 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 88 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 90 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* 98 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* a0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* a8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* b0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* b8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* c0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* c8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* d0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* d8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* e0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* e8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* f0 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    /* f8 */
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX },
+    { "(bad)",         XX, XX, XX, XX }
   },
 };
 
   },
 };
 
@@ -1772,7 +2670,7 @@ ckprefix (void)
        case 0x4d:
        case 0x4e:
        case 0x4f:
        case 0x4d:
        case 0x4e:
        case 0x4f:
-           if (mode_64bit)
+           if (address_mode == mode_64bit)
              newrex = *codep;
            else
              return;
              newrex = *codep;
            else
              return;
@@ -1814,7 +2712,7 @@ ckprefix (void)
          /* fwait is really an instruction.  If there are prefixes
             before the fwait, they belong to the fwait, *not* to the
             following instruction.  */
          /* fwait is really an instruction.  If there are prefixes
             before the fwait, they belong to the fwait, *not* to the
             following instruction.  */
-         if (prefixes)
+         if (prefixes || rex)
            {
              prefixes |= PREFIX_FWAIT;
              codep++;
            {
              prefixes |= PREFIX_FWAIT;
              codep++;
@@ -1828,8 +2726,8 @@ ckprefix (void)
       /* Rex is ignored when followed by another prefix.  */
       if (rex)
        {
       /* Rex is ignored when followed by another prefix.  */
       if (rex)
        {
-         oappend (prefix_name (rex, 0));
-         oappend (" ");
+         rex_used = rex;
+         return;
        }
       rex = newrex;
       codep++;
        }
       rex = newrex;
       codep++;
@@ -1898,7 +2796,7 @@ prefix_name (int pref, int sizeflag)
     case 0x66:
       return (sizeflag & DFLAG) ? "data16" : "data32";
     case 0x67:
     case 0x66:
       return (sizeflag & DFLAG) ? "data16" : "data32";
     case 0x67:
-      if (mode_64bit)
+      if (address_mode == mode_64bit)
        return (sizeflag & AFLAG) ? "addr32" : "addr64";
       else
        return (sizeflag & AFLAG) ? "addr16" : "addr32";
        return (sizeflag & AFLAG) ? "addr32" : "addr64";
       else
        return (sizeflag & AFLAG) ? "addr16" : "addr32";
@@ -1909,11 +2807,11 @@ prefix_name (int pref, int sizeflag)
     }
 }
 
     }
 }
 
-static char op1out[100], op2out[100], op3out[100];
-static int op_ad, op_index[3];
+static char op1out[100], op2out[100], op3out[100], op4out[100];
+static int op_ad, op_index[4];
 static int two_source_ops;
 static int two_source_ops;
-static bfd_vma op_address[3];
-static bfd_vma op_riprel[3];
+static bfd_vma op_address[4];
+static bfd_vma op_riprel[4];
 static bfd_vma start_pc;
 \f
 /*
 static bfd_vma start_pc;
 \f
 /*
@@ -1958,20 +2856,45 @@ print_insn_i386 (bfd_vma pc, disassemble_info *info)
   return print_insn (pc, info);
 }
 
   return print_insn (pc, info);
 }
 
+void
+print_i386_disassembler_options (FILE *stream)
+{
+  fprintf (stream, _("\n\
+The following i386/x86-64 specific disassembler options are supported for use\n\
+with the -M switch (multiple options should be separated by commas):\n"));
+
+  fprintf (stream, _("  x86-64      Disassemble in 64bit mode\n"));
+  fprintf (stream, _("  i386        Disassemble in 32bit mode\n"));
+  fprintf (stream, _("  i8086       Disassemble in 16bit mode\n"));
+  fprintf (stream, _("  att         Display instruction in AT&T syntax\n"));
+  fprintf (stream, _("  intel       Display instruction in Intel syntax\n"));
+  fprintf (stream, _("  addr64      Assume 64bit address size\n"));
+  fprintf (stream, _("  addr32      Assume 32bit address size\n"));
+  fprintf (stream, _("  addr16      Assume 16bit address size\n"));
+  fprintf (stream, _("  data32      Assume 32bit data size\n"));
+  fprintf (stream, _("  data16      Assume 16bit data size\n"));
+  fprintf (stream, _("  suffix      Always display instruction suffix in AT&T syntax\n"));
+}
+
 static int
 print_insn (bfd_vma pc, disassemble_info *info)
 {
   const struct dis386 *dp;
   int i;
 static int
 print_insn (bfd_vma pc, disassemble_info *info)
 {
   const struct dis386 *dp;
   int i;
-  char *first, *second, *third;
+  char *first, *second, *third, *fourth;
   int needcomma;
   int needcomma;
-  unsigned char uses_SSE_prefix, uses_LOCK_prefix;
+  unsigned char uses_DATA_prefix, uses_LOCK_prefix;
+  unsigned char uses_REPNZ_prefix, uses_REPZ_prefix;
   int sizeflag;
   const char *p;
   struct dis_private priv;
   int sizeflag;
   const char *p;
   struct dis_private priv;
+  unsigned char op;
 
 
-  mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
-               || info->mach == bfd_mach_x86_64);
+  if (info->mach == bfd_mach_x86_64_intel_syntax
+      || info->mach == bfd_mach_x86_64)
+    address_mode = mode_64bit;
+  else
+    address_mode = mode_32bit;
 
   if (intel_syntax == (char) -1)
     intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
 
   if (intel_syntax == (char) -1)
     intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
@@ -1989,44 +2912,54 @@ print_insn (bfd_vma pc, disassemble_info *info)
 
   for (p = info->disassembler_options; p != NULL; )
     {
 
   for (p = info->disassembler_options; p != NULL; )
     {
-      if (strncmp (p, "x86-64", 6) == 0)
+      if (CONST_STRNEQ (p, "x86-64"))
        {
        {
-         mode_64bit = 1;
+         address_mode = mode_64bit;
          priv.orig_sizeflag = AFLAG | DFLAG;
        }
          priv.orig_sizeflag = AFLAG | DFLAG;
        }
-      else if (strncmp (p, "i386", 4) == 0)
+      else if (CONST_STRNEQ (p, "i386"))
        {
        {
-         mode_64bit = 0;
+         address_mode = mode_32bit;
          priv.orig_sizeflag = AFLAG | DFLAG;
        }
          priv.orig_sizeflag = AFLAG | DFLAG;
        }
-      else if (strncmp (p, "i8086", 5) == 0)
+      else if (CONST_STRNEQ (p, "i8086"))
        {
        {
-         mode_64bit = 0;
+         address_mode = mode_16bit;
          priv.orig_sizeflag = 0;
        }
          priv.orig_sizeflag = 0;
        }
-      else if (strncmp (p, "intel", 5) == 0)
+      else if (CONST_STRNEQ (p, "intel"))
        {
          intel_syntax = 1;
        }
        {
          intel_syntax = 1;
        }
-      else if (strncmp (p, "att", 3) == 0)
+      else if (CONST_STRNEQ (p, "att"))
        {
          intel_syntax = 0;
        }
        {
          intel_syntax = 0;
        }
-      else if (strncmp (p, "addr", 4) == 0)
+      else if (CONST_STRNEQ (p, "addr"))
        {
        {
-         if (p[4] == '1' && p[5] == '6')
-           priv.orig_sizeflag &= ~AFLAG;
-         else if (p[4] == '3' && p[5] == '2')
-           priv.orig_sizeflag |= AFLAG;
+         if (address_mode == mode_64bit)
+           {
+             if (p[4] == '3' && p[5] == '2')
+               priv.orig_sizeflag &= ~AFLAG;
+             else if (p[4] == '6' && p[5] == '4')
+               priv.orig_sizeflag |= AFLAG;
+           }
+         else
+           {
+             if (p[4] == '1' && p[5] == '6')
+               priv.orig_sizeflag &= ~AFLAG;
+             else if (p[4] == '3' && p[5] == '2')
+               priv.orig_sizeflag |= AFLAG;
+           }
        }
        }
-      else if (strncmp (p, "data", 4) == 0)
+      else if (CONST_STRNEQ (p, "data"))
        {
          if (p[4] == '1' && p[5] == '6')
            priv.orig_sizeflag &= ~DFLAG;
          else if (p[4] == '3' && p[5] == '2')
            priv.orig_sizeflag |= DFLAG;
        }
        {
          if (p[4] == '1' && p[5] == '6')
            priv.orig_sizeflag &= ~DFLAG;
          else if (p[4] == '3' && p[5] == '2')
            priv.orig_sizeflag |= DFLAG;
        }
-      else if (strncmp (p, "suffix", 6) == 0)
+      else if (CONST_STRNEQ (p, "suffix"))
        priv.orig_sizeflag |= SUFFIX_ALWAYS;
 
       p = strchr (p, ',');
        priv.orig_sizeflag |= SUFFIX_ALWAYS;
 
       p = strchr (p, ',');
@@ -2075,8 +3008,9 @@ print_insn (bfd_vma pc, disassemble_info *info)
   op1out[0] = 0;
   op2out[0] = 0;
   op3out[0] = 0;
   op1out[0] = 0;
   op2out[0] = 0;
   op3out[0] = 0;
+  op4out[0] = 0;
 
 
-  op_index[0] = op_index[1] = op_index[2] = -1;
+  op_index[0] = op_index[1] = op_index[2] = op_index[3] = -1;
 
   the_info = info;
   start_pc = pc;
 
   the_info = info;
   start_pc = pc;
@@ -2117,13 +3051,14 @@ print_insn (bfd_vma pc, disassemble_info *info)
   FETCH_DATA (info, codep + 1);
   two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
 
   FETCH_DATA (info, codep + 1);
   two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
 
-  if ((prefixes & PREFIX_FWAIT)
-      && ((*codep < 0xd8) || (*codep > 0xdf)))
+  if (((prefixes & PREFIX_FWAIT)
+       && ((*codep < 0xd8) || (*codep > 0xdf)))
+      || (rex && rex_used))
     {
       const char *name;
 
     {
       const char *name;
 
-      /* fwait not followed by floating point instruction.  Print the
-        first prefix, which is probably fwait itself.  */
+      /* fwait not followed by floating point instruction, or rex followed
+        by other prefixes.  Print the first prefix.  */
       name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
       if (name == NULL)
        name = INTERNAL_DISASSEMBLER_ERROR;
       name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
       if (name == NULL)
        name = INTERNAL_DISASSEMBLER_ERROR;
@@ -2131,33 +3066,62 @@ print_insn (bfd_vma pc, disassemble_info *info)
       return 1;
     }
 
       return 1;
     }
 
+  op = 0;
   if (*codep == 0x0f)
     {
   if (*codep == 0x0f)
     {
+      unsigned char threebyte;
       FETCH_DATA (info, codep + 2);
       FETCH_DATA (info, codep + 2);
-      dp = &dis386_twobyte[*++codep];
+      threebyte = *++codep;
+      dp = &dis386_twobyte[threebyte];
       need_modrm = twobyte_has_modrm[*codep];
       need_modrm = twobyte_has_modrm[*codep];
-      uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep];
+      uses_DATA_prefix = twobyte_uses_DATA_prefix[*codep];
+      uses_REPNZ_prefix = twobyte_uses_REPNZ_prefix[*codep];
+      uses_REPZ_prefix = twobyte_uses_REPZ_prefix[*codep];
       uses_LOCK_prefix = (*codep & ~0x02) == 0x20;
       uses_LOCK_prefix = (*codep & ~0x02) == 0x20;
+      codep++;
+      if (dp->name == NULL && dp->bytemode1 == IS_3BYTE_OPCODE)
+       {
+         FETCH_DATA (info, codep + 2);
+         op = *codep++;
+         switch (threebyte)
+           {
+           case 0x38:
+             uses_DATA_prefix = threebyte_0x38_uses_DATA_prefix[op];
+             uses_REPNZ_prefix = threebyte_0x38_uses_REPNZ_prefix[op];
+             uses_REPZ_prefix = threebyte_0x38_uses_REPZ_prefix[op];
+             break;
+           case 0x3a:
+             uses_DATA_prefix = threebyte_0x3a_uses_DATA_prefix[op];
+             uses_REPNZ_prefix = threebyte_0x3a_uses_REPNZ_prefix[op];
+             uses_REPZ_prefix = threebyte_0x3a_uses_REPZ_prefix[op];
+             break;
+           default:
+             break;
+           }
+       }
     }
   else
     {
       dp = &dis386[*codep];
       need_modrm = onebyte_has_modrm[*codep];
     }
   else
     {
       dp = &dis386[*codep];
       need_modrm = onebyte_has_modrm[*codep];
-      uses_SSE_prefix = 0;
+      uses_DATA_prefix = 0;
+      uses_REPNZ_prefix = 0;
+      uses_REPZ_prefix = 0;
       uses_LOCK_prefix = 0;
       uses_LOCK_prefix = 0;
+      codep++;
     }
     }
-  codep++;
-
-  if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ))
+  
+  if (!uses_REPZ_prefix && (prefixes & PREFIX_REPZ))
     {
       oappend ("repz ");
       used_prefixes |= PREFIX_REPZ;
     }
     {
       oappend ("repz ");
       used_prefixes |= PREFIX_REPZ;
     }
-  if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ))
+  if (!uses_REPNZ_prefix && (prefixes & PREFIX_REPNZ))
     {
       oappend ("repnz ");
       used_prefixes |= PREFIX_REPNZ;
     }
     {
       oappend ("repnz ");
       used_prefixes |= PREFIX_REPNZ;
     }
+
   if (!uses_LOCK_prefix && (prefixes & PREFIX_LOCK))
     {
       oappend ("lock ");
   if (!uses_LOCK_prefix && (prefixes & PREFIX_LOCK))
     {
       oappend ("lock ");
@@ -2169,7 +3133,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
       sizeflag ^= AFLAG;
       if (dp->bytemode3 != loop_jcxz_mode || intel_syntax)
        {
       sizeflag ^= AFLAG;
       if (dp->bytemode3 != loop_jcxz_mode || intel_syntax)
        {
-         if ((sizeflag & AFLAG) || mode_64bit)
+         if ((sizeflag & AFLAG) || address_mode == mode_64bit)
            oappend ("addr32 ");
          else
            oappend ("addr16 ");
            oappend ("addr32 ");
          else
            oappend ("addr16 ");
@@ -2177,7 +3141,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
        }
     }
 
        }
     }
 
-  if (!uses_SSE_prefix && (prefixes & PREFIX_DATA))
+  if (!uses_DATA_prefix && (prefixes & PREFIX_DATA))
     {
       sizeflag ^= DFLAG;
       if (dp->bytemode3 == cond_jump_mode
     {
       sizeflag ^= DFLAG;
       if (dp->bytemode3 == cond_jump_mode
@@ -2192,7 +3156,14 @@ print_insn (bfd_vma pc, disassemble_info *info)
        }
     }
 
        }
     }
 
-  if (need_modrm)
+  if (dp->name == NULL && dp->bytemode1 == IS_3BYTE_OPCODE)
+    {
+      dp = &three_byte_table[dp->bytemode2][op];
+      mod = (*codep >> 6) & 3;
+      reg = (*codep >> 3) & 7;
+      rm = *codep & 7;
+    }
+  else if (need_modrm)
     {
       FETCH_DATA (info, codep + 1);
       mod = (*codep >> 6) & 3;
     {
       FETCH_DATA (info, codep + 1);
       mod = (*codep >> 6) & 3;
@@ -2222,21 +3193,24 @@ print_insn (bfd_vma pc, disassemble_info *info)
                index = 1;
              else
                {
                index = 1;
              else
                {
-                 used_prefixes |= (prefixes & PREFIX_DATA);
-                 if (prefixes & PREFIX_DATA)
-                   index = 2;
+                 /* We should check PREFIX_REPNZ and PREFIX_REPZ
+                    before PREFIX_DATA.  */
+                 used_prefixes |= (prefixes & PREFIX_REPNZ);
+                 if (prefixes & PREFIX_REPNZ)
+                   index = 3;
                  else
                    {
                  else
                    {
-                     used_prefixes |= (prefixes & PREFIX_REPNZ);
-                     if (prefixes & PREFIX_REPNZ)
-                       index = 3;
+                     used_prefixes |= (prefixes & PREFIX_DATA);
+                     if (prefixes & PREFIX_DATA)
+                       index = 2;
                    }
                }
              dp = &prefix_user_table[dp->bytemode2][index];
              break;
 
            case X86_64_SPECIAL:
                    }
                }
              dp = &prefix_user_table[dp->bytemode2][index];
              break;
 
            case X86_64_SPECIAL:
-             dp = &x86_64_table[dp->bytemode2][mode_64bit];
+             index = address_mode == mode_64bit ? 1 : 0;
+             dp = &x86_64_table[dp->bytemode2][index];
              break;
 
            default:
              break;
 
            default:
@@ -2248,19 +3222,24 @@ print_insn (bfd_vma pc, disassemble_info *info)
       if (putop (dp->name, sizeflag) == 0)
        {
          obufp = op1out;
       if (putop (dp->name, sizeflag) == 0)
        {
          obufp = op1out;
-         op_ad = 2;
+         op_ad = 3;
          if (dp->op1)
            (*dp->op1) (dp->bytemode1, sizeflag);
 
          obufp = op2out;
          if (dp->op1)
            (*dp->op1) (dp->bytemode1, sizeflag);
 
          obufp = op2out;
-         op_ad = 1;
+         op_ad = 2;
          if (dp->op2)
            (*dp->op2) (dp->bytemode2, sizeflag);
 
          obufp = op3out;
          if (dp->op2)
            (*dp->op2) (dp->bytemode2, sizeflag);
 
          obufp = op3out;
-         op_ad = 0;
+         op_ad = 1;
          if (dp->op3)
            (*dp->op3) (dp->bytemode3, sizeflag);
          if (dp->op3)
            (*dp->op3) (dp->bytemode3, sizeflag);
+
+         obufp = op4out;
+         op_ad = 0;
+         if (dp->op4)
+           (*dp->op4) (dp->bytemode4, sizeflag);
        }
     }
 
        }
     }
 
@@ -2300,15 +3279,21 @@ print_insn (bfd_vma pc, disassemble_info *info)
       first = op1out;
       second = op2out;
       third = op3out;
       first = op1out;
       second = op2out;
       third = op3out;
+      fourth = op4out;
       op_ad = op_index[0];
       op_ad = op_index[0];
-      op_index[0] = op_index[2];
+      op_index[0] = op_index[3];
+      op_index[3] = op_ad;
+      op_ad = op_index[1];
+      op_index[1] = op_index[2];
       op_index[2] = op_ad;
       op_index[2] = op_ad;
+
     }
   else
     {
     }
   else
     {
-      first = op3out;
-      second = op2out;
-      third = op1out;
+      first = op4out;
+      second = op3out;
+      third = op2out;
+      fourth = op1out;
     }
   needcomma = 0;
   if (*first)
     }
   needcomma = 0;
   if (*first)
@@ -2319,6 +3304,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
        (*info->fprintf_func) (info->stream, "%s", first);
       needcomma = 1;
     }
        (*info->fprintf_func) (info->stream, "%s", first);
       needcomma = 1;
     }
+  
   if (*second)
     {
       if (needcomma)
   if (*second)
     {
       if (needcomma)
@@ -2329,6 +3315,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
        (*info->fprintf_func) (info->stream, "%s", second);
       needcomma = 1;
     }
        (*info->fprintf_func) (info->stream, "%s", second);
       needcomma = 1;
     }
+
   if (*third)
     {
       if (needcomma)
   if (*third)
     {
       if (needcomma)
@@ -2337,8 +3324,20 @@ print_insn (bfd_vma pc, disassemble_info *info)
        (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
       else
        (*info->fprintf_func) (info->stream, "%s", third);
        (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
       else
        (*info->fprintf_func) (info->stream, "%s", third);
+      needcomma = 1;
+    }
+
+  if (*fourth)
+    {
+      if (needcomma)
+       (*info->fprintf_func) (info->stream, ",");
+      if (op_index[3] != -1 && !op_riprel[3])
+       (*info->print_address_func) ((bfd_vma) op_address[op_index[3]], info);
+      else
+       (*info->fprintf_func) (info->stream, "%s", fourth);
     }
     }
-  for (i = 0; i < 3; i++)
+
+  for (i = 0; i < 4; i++)
     if (op_index[i] != -1 && op_riprel[i])
       {
        (*info->fprintf_func) (info->stream, "        # ");
     if (op_index[i] != -1 && op_riprel[i])
       {
        (*info->fprintf_func) (info->stream, "        # ");
@@ -2501,34 +3500,34 @@ static const unsigned char float_mem_mode[] = {
 #define ST OP_ST, 0
 #define STi OP_STi, 0
 
 #define ST OP_ST, 0
 #define STi OP_STi, 0
 
-#define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0
-#define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0
-#define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0
-#define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0
-#define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0
-#define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0
-#define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0
-#define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0
-#define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0
+#define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0, NULL, 0
+#define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0, NULL, 0
+#define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0, NULL, 0
+#define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0, NULL, 0
+#define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0, NULL, 0
+#define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0, NULL, 0
+#define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0, NULL, 0
+#define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0, NULL, 0
 
 static const struct dis386 float_reg[][8] = {
   /* d8 */
   {
 
 static const struct dis386 float_reg[][8] = {
   /* d8 */
   {
-    { "fadd",  ST, STi, XX },
-    { "fmul",  ST, STi, XX },
-    { "fcom",  STi, XX, XX },
-    { "fcomp", STi, XX, XX },
-    { "fsub",  ST, STi, XX },
-    { "fsubr", ST, STi, XX },
-    { "fdiv",  ST, STi, XX },
-    { "fdivr", ST, STi, XX },
+    { "fadd",  ST, STi, XX, XX },
+    { "fmul",  ST, STi, XX, XX },
+    { "fcom",  STi, XX, XX, XX },
+    { "fcomp", STi, XX, XX, XX },
+    { "fsub",  ST, STi, XX, XX },
+    { "fsubr", ST, STi, XX, XX },
+    { "fdiv",  ST, STi, XX, XX },
+    { "fdivr", ST, STi, XX, XX },
   },
   /* d9 */
   {
   },
   /* d9 */
   {
-    { "fld",   STi, XX, XX },
-    { "fxch",  STi, XX, XX },
+    { "fld",   STi, XX, XX, XX },
+    { "fxch",  STi, XX, XX, XX },
     { FGRPd9_2 },
     { FGRPd9_2 },
-    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
     { FGRPd9_4 },
     { FGRPd9_5 },
     { FGRPd9_6 },
     { FGRPd9_4 },
     { FGRPd9_5 },
     { FGRPd9_6 },
@@ -2536,83 +3535,83 @@ static const struct dis386 float_reg[][8] = {
   },
   /* da */
   {
   },
   /* da */
   {
-    { "fcmovb",        ST, STi, XX },
-    { "fcmove",        ST, STi, XX },
-    { "fcmovbe",ST, STi, XX },
-    { "fcmovu",        ST, STi, XX },
-    { "(bad)", XX, XX, XX },
+    { "fcmovb",        ST, STi, XX, XX },
+    { "fcmove",        ST, STi, XX, XX },
+    { "fcmovbe",ST, STi, XX, XX },
+    { "fcmovu",        ST, STi, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
     { FGRPda_5 },
     { FGRPda_5 },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* db */
   {
   },
   /* db */
   {
-    { "fcmovnb",ST, STi, XX },
-    { "fcmovne",ST, STi, XX },
-    { "fcmovnbe",ST, STi, XX },
-    { "fcmovnu",ST, STi, XX },
+    { "fcmovnb",ST, STi, XX, XX },
+    { "fcmovne",ST, STi, XX, XX },
+    { "fcmovnbe",ST, STi, XX, XX },
+    { "fcmovnu",ST, STi, XX, XX },
     { FGRPdb_4 },
     { FGRPdb_4 },
-    { "fucomi",        ST, STi, XX },
-    { "fcomi", ST, STi, XX },
-    { "(bad)", XX, XX, XX },
+    { "fucomi",        ST, STi, XX, XX },
+    { "fcomi", ST, STi, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* dc */
   {
   },
   /* dc */
   {
-    { "fadd",  STi, ST, XX },
-    { "fmul",  STi, ST, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
+    { "fadd",  STi, ST, XX, XX },
+    { "fmul",  STi, ST, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
 #if UNIXWARE_COMPAT
 #if UNIXWARE_COMPAT
-    { "fsub",  STi, ST, XX },
-    { "fsubr", STi, ST, XX },
-    { "fdiv",  STi, ST, XX },
-    { "fdivr", STi, ST, XX },
+    { "fsub",  STi, ST, XX, XX },
+    { "fsubr", STi, ST, XX, XX },
+    { "fdiv",  STi, ST, XX, XX },
+    { "fdivr", STi, ST, XX, XX },
 #else
 #else
-    { "fsubr", STi, ST, XX },
-    { "fsub",  STi, ST, XX },
-    { "fdivr", STi, ST, XX },
-    { "fdiv",  STi, ST, XX },
+    { "fsubr", STi, ST, XX, XX },
+    { "fsub",  STi, ST, XX, XX },
+    { "fdivr", STi, ST, XX, XX },
+    { "fdiv",  STi, ST, XX, XX },
 #endif
   },
   /* dd */
   {
 #endif
   },
   /* dd */
   {
-    { "ffree", STi, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "fst",   STi, XX, XX },
-    { "fstp",  STi, XX, XX },
-    { "fucom", STi, XX, XX },
-    { "fucomp",        STi, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
+    { "ffree", STi, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "fst",   STi, XX, XX, XX },
+    { "fstp",  STi, XX, XX, XX },
+    { "fucom", STi, XX, XX, XX },
+    { "fucomp",        STi, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
   /* de */
   {
   },
   /* de */
   {
-    { "faddp", STi, ST, XX },
-    { "fmulp", STi, ST, XX },
-    { "(bad)", XX, XX, XX },
+    { "faddp", STi, ST, XX, XX },
+    { "fmulp", STi, ST, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
     { FGRPde_3 },
 #if UNIXWARE_COMPAT
     { FGRPde_3 },
 #if UNIXWARE_COMPAT
-    { "fsubp", STi, ST, XX },
-    { "fsubrp",        STi, ST, XX },
-    { "fdivp", STi, ST, XX },
-    { "fdivrp",        STi, ST, XX },
+    { "fsubp", STi, ST, XX, XX },
+    { "fsubrp",        STi, ST, XX, XX },
+    { "fdivp", STi, ST, XX, XX },
+    { "fdivrp",        STi, ST, XX, XX },
 #else
 #else
-    { "fsubrp",        STi, ST, XX },
-    { "fsubp", STi, ST, XX },
-    { "fdivrp",        STi, ST, XX },
-    { "fdivp", STi, ST, XX },
+    { "fsubrp",        STi, ST, XX, XX },
+    { "fsubp", STi, ST, XX, XX },
+    { "fdivrp",        STi, ST, XX, XX },
+    { "fdivp", STi, ST, XX, XX },
 #endif
   },
   /* df */
   {
 #endif
   },
   /* df */
   {
-    { "ffreep",        STi, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
-    { "(bad)", XX, XX, XX },
+    { "ffreep",        STi, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
     { FGRPdf_4 },
     { FGRPdf_4 },
-    { "fucomip",ST, STi, XX },
-    { "fcomip", ST, STi, XX },
-    { "(bad)", XX, XX, XX },
+    { "fucomip",ST, STi, XX, XX },
+    { "fcomip", ST, STi, XX, XX },
+    { "(bad)", XX, XX, XX, XX },
   },
 };
 
   },
 };
 
@@ -2678,6 +3677,7 @@ dofloat (int sizeflag)
 
       putop (float_mem[fp_indx], sizeflag);
       obufp = op1out;
 
       putop (float_mem[fp_indx], sizeflag);
       obufp = op1out;
+      op_ad = 2;
       OP_E (float_mem_mode[fp_indx], sizeflag);
       return;
     }
       OP_E (float_mem_mode[fp_indx], sizeflag);
       return;
     }
@@ -2699,9 +3699,12 @@ dofloat (int sizeflag)
       putop (dp->name, sizeflag);
 
       obufp = op1out;
       putop (dp->name, sizeflag);
 
       obufp = op1out;
+      op_ad = 2;
       if (dp->op1)
        (*dp->op1) (dp->bytemode1, sizeflag);
       if (dp->op1)
        (*dp->op1) (dp->bytemode1, sizeflag);
+
       obufp = op2out;
       obufp = op2out;
+      op_ad = 1;
       if (dp->op2)
        (*dp->op2) (dp->bytemode2, sizeflag);
     }
       if (dp->op2)
        (*dp->op2) (dp->bytemode2, sizeflag);
     }
@@ -2710,7 +3713,7 @@ dofloat (int sizeflag)
 static void
 OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
 {
 static void
 OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
 {
-  oappend ("%st");
+  oappend ("%st" + intel_syntax);
 }
 
 static void
 }
 
 static void
@@ -2738,7 +3741,7 @@ putop (const char *template, int sizeflag)
          alt = 0;
          if (intel_syntax)
            alt += 1;
          alt = 0;
          if (intel_syntax)
            alt += 1;
-         if (mode_64bit)
+         if (address_mode == mode_64bit)
            alt += 2;
          while (alt != 0)
            {
            alt += 2;
          while (alt != 0)
            {
@@ -2793,8 +3796,25 @@ putop (const char *template, int sizeflag)
              used_prefixes |= (prefixes & PREFIX_DATA);
            }
          break;
              used_prefixes |= (prefixes & PREFIX_DATA);
            }
          break;
+       case 'D':
+         if (intel_syntax || !(sizeflag & SUFFIX_ALWAYS))
+           break;
+         USED_REX (REX_MODE64);
+         if (mod == 3)
+           {
+             if (rex & REX_MODE64)
+               *obufp++ = 'q';
+             else if (sizeflag & DFLAG)
+               *obufp++ = intel_syntax ? 'd' : 'l';
+             else
+               *obufp++ = 'w';
+             used_prefixes |= (prefixes & PREFIX_DATA);
+           }
+         else
+           *obufp++ = 'w';
+         break;
        case 'E':               /* For jcxz/jecxz */
        case 'E':               /* For jcxz/jecxz */
-         if (mode_64bit)
+         if (address_mode == mode_64bit)
            {
              if (sizeflag & AFLAG)
                *obufp++ = 'r';
            {
              if (sizeflag & AFLAG)
                *obufp++ = 'r';
@@ -2812,12 +3832,22 @@ putop (const char *template, int sizeflag)
          if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
            {
              if (sizeflag & AFLAG)
          if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
            {
              if (sizeflag & AFLAG)
-               *obufp++ = mode_64bit ? 'q' : 'l';
+               *obufp++ = address_mode == mode_64bit ? 'q' : 'l';
              else
              else
-               *obufp++ = mode_64bit ? 'l' : 'w';
+               *obufp++ = address_mode == mode_64bit ? 'l' : 'w';
              used_prefixes |= (prefixes & PREFIX_ADDR);
            }
          break;
              used_prefixes |= (prefixes & PREFIX_ADDR);
            }
          break;
+       case 'G':
+         if (intel_syntax || (obufp[-1] != 's' && !(sizeflag & SUFFIX_ALWAYS)))
+           break;
+         if ((rex & REX_MODE64) || (sizeflag & DFLAG))
+           *obufp++ = 'l';
+         else
+           *obufp++ = 'w';
+         if (!(rex & REX_MODE64))
+           used_prefixes |= (prefixes & PREFIX_DATA);
+         break;
        case 'H':
          if (intel_syntax)
            break;
        case 'H':
          if (intel_syntax)
            break;
@@ -2838,6 +3868,15 @@ putop (const char *template, int sizeflag)
            break;
          *obufp++ = 'l';
          break;
            break;
          *obufp++ = 'l';
          break;
+       case 'Z':
+         if (intel_syntax)
+           break;
+         if (address_mode == mode_64bit && (sizeflag & SUFFIX_ALWAYS))
+           {
+             *obufp++ = 'q';
+             break;
+           }
+         /* Fall through.  */
        case 'L':
          if (intel_syntax)
            break;
        case 'L':
          if (intel_syntax)
            break;
@@ -2854,13 +3893,17 @@ putop (const char *template, int sizeflag)
          USED_REX (REX_MODE64);
          if (rex & REX_MODE64)
            *obufp++ = 'o';
          USED_REX (REX_MODE64);
          if (rex & REX_MODE64)
            *obufp++ = 'o';
+         else if (intel_syntax && (sizeflag & DFLAG))
+           *obufp++ = 'q';
          else
            *obufp++ = 'd';
          else
            *obufp++ = 'd';
+         if (!(rex & REX_MODE64))
+           used_prefixes |= (prefixes & PREFIX_DATA);
          break;
        case 'T':
          if (intel_syntax)
            break;
          break;
        case 'T':
          if (intel_syntax)
            break;
-         if (mode_64bit)
+         if (address_mode == mode_64bit && (sizeflag & DFLAG))
            {
              *obufp++ = 'q';
              break;
            {
              *obufp++ = 'q';
              break;
@@ -2882,16 +3925,17 @@ putop (const char *template, int sizeflag)
                      *obufp++ = 'l';
                   else
                     *obufp++ = 'w';
                      *obufp++ = 'l';
                   else
                     *obufp++ = 'w';
-                  used_prefixes |= (prefixes & PREFIX_DATA);
                }
                }
+             used_prefixes |= (prefixes & PREFIX_DATA);
            }
          break;
        case 'U':
          if (intel_syntax)
            break;
            }
          break;
        case 'U':
          if (intel_syntax)
            break;
-         if (mode_64bit)
+         if (address_mode == mode_64bit && (sizeflag & DFLAG))
            {
            {
-             *obufp++ = 'q';
+             if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
+               *obufp++ = 'q';
              break;
            }
          /* Fall through.  */
              break;
            }
          /* Fall through.  */
@@ -2909,42 +3953,39 @@ putop (const char *template, int sizeflag)
                    *obufp++ = intel_syntax ? 'd' : 'l';
                  else
                    *obufp++ = 'w';
                    *obufp++ = intel_syntax ? 'd' : 'l';
                  else
                    *obufp++ = 'w';
-                 used_prefixes |= (prefixes & PREFIX_DATA);
                }
                }
+             used_prefixes |= (prefixes & PREFIX_DATA);
            }
          break;
        case 'R':
          USED_REX (REX_MODE64);
            }
          break;
        case 'R':
          USED_REX (REX_MODE64);
-         if (intel_syntax)
+         if (rex & REX_MODE64)
+           *obufp++ = 'q';
+         else if (sizeflag & DFLAG)
            {
            {
-             if (rex & REX_MODE64)
-               {
-                 *obufp++ = 'q';
-                 *obufp++ = 't';
-               }
-             else if (sizeflag & DFLAG)
-               {
+             if (intel_syntax)
                  *obufp++ = 'd';
                  *obufp++ = 'd';
-                 *obufp++ = 'q';
-               }
              else
              else
-               {
-                 *obufp++ = 'w';
-                 *obufp++ = 'd';
-               }
+                 *obufp++ = 'l';
            }
          else
            }
          else
-           {
-             if (rex & REX_MODE64)
-               *obufp++ = 'q';
-             else if (sizeflag & DFLAG)
-               *obufp++ = 'l';
-             else
-               *obufp++ = 'w';
-           }
+           *obufp++ = 'w';
+         if (intel_syntax && !p[1]
+             && ((rex & REX_MODE64) || (sizeflag & DFLAG)))
+           *obufp++ = 'e';
          if (!(rex & REX_MODE64))
            used_prefixes |= (prefixes & PREFIX_DATA);
          break;
          if (!(rex & REX_MODE64))
            used_prefixes |= (prefixes & PREFIX_DATA);
          break;
+       case 'V':
+         if (intel_syntax)
+           break;
+         if (address_mode == mode_64bit && (sizeflag & DFLAG))
+           {
+             if (sizeflag & SUFFIX_ALWAYS)
+               *obufp++ = 'q';
+             break;
+           }
+         /* Fall through.  */
        case 'S':
          if (intel_syntax)
            break;
        case 'S':
          if (intel_syntax)
            break;
@@ -2981,31 +4022,19 @@ putop (const char *template, int sizeflag)
          /* implicit operand size 'l' for i386 or 'q' for x86-64 */
        case 'W':
          /* operand size flag for cwtl, cbtw */
          /* implicit operand size 'l' for i386 or 'q' for x86-64 */
        case 'W':
          /* operand size flag for cwtl, cbtw */
-         USED_REX (0);
-         if (rex)
-           *obufp++ = 'l';
+         USED_REX (REX_MODE64);
+         if (rex & REX_MODE64)
+           {
+             if (intel_syntax)
+               *obufp++ = 'd';
+             else
+               *obufp++ = 'l';
+           }
          else if (sizeflag & DFLAG)
            *obufp++ = 'w';
          else
            *obufp++ = 'b';
          else if (sizeflag & DFLAG)
            *obufp++ = 'w';
          else
            *obufp++ = 'b';
-         if (intel_syntax)
-           {
-             if (rex)
-               {
-                 *obufp++ = 'q';
-                 *obufp++ = 'e';
-               }
-             if (sizeflag & DFLAG)
-               {
-                 *obufp++ = 'd';
-                 *obufp++ = 'e';
-               }
-             else
-               {
-                 *obufp++ = 'w';
-               }
-           }
-         if (!rex)
+         if (!(rex & REX_MODE64))
            used_prefixes |= (prefixes & PREFIX_DATA);
          break;
        }
            used_prefixes |= (prefixes & PREFIX_DATA);
          break;
        }
@@ -3068,7 +4097,7 @@ OP_indirE (int bytemode, int sizeflag)
 static void
 print_operand_value (char *buf, int hex, bfd_vma disp)
 {
 static void
 print_operand_value (char *buf, int hex, bfd_vma disp)
 {
-  if (mode_64bit)
+  if (address_mode == mode_64bit)
     {
       if (hex)
        {
     {
       if (hex)
        {
@@ -3134,8 +4163,8 @@ intel_operand_size (int bytemode, int sizeflag)
     case dqw_mode:
       oappend ("WORD PTR ");
       break;
     case dqw_mode:
       oappend ("WORD PTR ");
       break;
-    case branch_v_mode:
-      if (mode_64bit && (sizeflag & DFLAG))
+    case stack_v_mode:
+      if (address_mode == mode_64bit && (sizeflag & DFLAG))
        {
          oappend ("QWORD PTR ");
          used_prefixes |= (prefixes & PREFIX_DATA);
        {
          oappend ("QWORD PTR ");
          used_prefixes |= (prefixes & PREFIX_DATA);
@@ -3153,6 +4182,13 @@ intel_operand_size (int bytemode, int sizeflag)
        oappend ("WORD PTR ");
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
        oappend ("WORD PTR ");
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
+    case z_mode:
+      if ((rex & REX_MODE64) || (sizeflag & DFLAG))
+       *obufp++ = 'D';
+      oappend ("WORD PTR ");
+      if (!(rex & REX_MODE64))
+       used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
     case d_mode:
       oappend ("DWORD PTR ");
       break;
     case d_mode:
       oappend ("DWORD PTR ");
       break;
@@ -3160,7 +4196,7 @@ intel_operand_size (int bytemode, int sizeflag)
       oappend ("QWORD PTR ");
       break;
     case m_mode:
       oappend ("QWORD PTR ");
       break;
     case m_mode:
-      if (mode_64bit)
+      if (address_mode == mode_64bit)
        oappend ("QWORD PTR ");
       else
        oappend ("DWORD PTR ");
        oappend ("QWORD PTR ");
       else
        oappend ("DWORD PTR ");
@@ -3178,6 +4214,9 @@ intel_operand_size (int bytemode, int sizeflag)
     case x_mode:
       oappend ("XMMWORD PTR ");
       break;
     case x_mode:
       oappend ("XMMWORD PTR ");
       break;
+    case o_mode:
+      oappend ("OWORD PTR ");
+      break;
     default:
       break;
     }
     default:
       break;
     }
@@ -3218,23 +4257,20 @@ OP_E (int bytemode, int sizeflag)
          oappend (names64[rm + add]);
          break;
        case m_mode:
          oappend (names64[rm + add]);
          break;
        case m_mode:
-         if (mode_64bit)
+         if (address_mode == mode_64bit)
            oappend (names64[rm + add]);
          else
            oappend (names32[rm + add]);
          break;
            oappend (names64[rm + add]);
          else
            oappend (names32[rm + add]);
          break;
-       case branch_v_mode:
-         if (mode_64bit)
-           oappend (names64[rm + add]);
-         else
+       case stack_v_mode:
+         if (address_mode == mode_64bit && (sizeflag & DFLAG))
            {
            {
-             if ((sizeflag & DFLAG) || bytemode != branch_v_mode)
-               oappend (names32[rm + add]);
-             else
-               oappend (names16[rm + add]);
+             oappend (names64[rm + add]);
              used_prefixes |= (prefixes & PREFIX_DATA);
              used_prefixes |= (prefixes & PREFIX_DATA);
+             break;
            }
            }
-         break;
+         bytemode = v_mode;
+         /* FALLTHRU */
        case v_mode:
        case dq_mode:
        case dqw_mode:
        case v_mode:
        case dq_mode:
        case dqw_mode:
@@ -3261,7 +4297,7 @@ OP_E (int bytemode, int sizeflag)
     intel_operand_size (bytemode, sizeflag);
   append_seg ();
 
     intel_operand_size (bytemode, sizeflag);
   append_seg ();
 
-  if ((sizeflag & AFLAG) || mode_64bit) /* 32 bit address mode */
+  if ((sizeflag & AFLAG) || address_mode == mode_64bit) /* 32 bit address mode */
     {
       int havesib;
       int havebase;
     {
       int havesib;
       int havebase;
@@ -3278,7 +4314,7 @@ OP_E (int bytemode, int sizeflag)
          havesib = 1;
          FETCH_DATA (the_info, codep + 1);
          index = (*codep >> 3) & 7;
          havesib = 1;
          FETCH_DATA (the_info, codep + 1);
          index = (*codep >> 3) & 7;
-         if (mode_64bit || index != 0x4)
+         if (address_mode == mode_64bit || index != 0x4)
            /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored.  */
            scale = (*codep >> 6) & 3;
          base = *codep & 7;
            /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored.  */
            scale = (*codep >> 6) & 3;
          base = *codep & 7;
@@ -3295,7 +4331,7 @@ OP_E (int bytemode, int sizeflag)
          if ((base & 7) == 5)
            {
              havebase = 0;
          if ((base & 7) == 5)
            {
              havebase = 0;
-             if (mode_64bit && !havesib)
+             if (address_mode == mode_64bit && !havesib)
                riprel = 1;
              disp = get32s ();
            }
                riprel = 1;
              disp = get32s ();
            }
@@ -3330,7 +4366,7 @@ OP_E (int bytemode, int sizeflag)
            oappend ("rip + ");
          *obufp = '\0';
          if (havebase)
            oappend ("rip + ");
          *obufp = '\0';
          if (havebase)
-           oappend (mode_64bit && (sizeflag & AFLAG)
+           oappend (address_mode == mode_64bit && (sizeflag & AFLAG)
                     ? names64[base] : names32[base]);
          if (havesib)
            {
                     ? names64[base] : names32[base]);
          if (havesib)
            {
@@ -3341,7 +4377,7 @@ OP_E (int bytemode, int sizeflag)
                      *obufp++ = separator_char;
                      *obufp = '\0';
                    }
                      *obufp++ = separator_char;
                      *obufp = '\0';
                    }
-                 oappend (mode_64bit && (sizeflag & AFLAG)
+                 oappend (address_mode == mode_64bit && (sizeflag & AFLAG)
                           ? names64[index] : names32[index]);
                }
              if (scale != 0 || (!intel_syntax && index != 4))
                           ? names64[index] : names32[index]);
                }
              if (scale != 0 || (!intel_syntax && index != 4))
@@ -3502,7 +4538,7 @@ OP_G (int bytemode, int sizeflag)
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
     case m_mode:
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
     case m_mode:
-      if (mode_64bit)
+      if (address_mode == mode_64bit)
        oappend (names64[reg + add]);
       else
        oappend (names32[reg + add]);
        oappend (names64[reg + add]);
       else
        oappend (names32[reg + add]);
@@ -3582,7 +4618,7 @@ static void
 set_op (bfd_vma op, int riprel)
 {
   op_index[op_ad] = op_ad;
 set_op (bfd_vma op, int riprel)
 {
   op_index[op_ad] = op_ad;
-  if (mode_64bit)
+  if (address_mode == mode_64bit)
     {
       op_address[op_ad] = op;
       op_riprel[op_ad] = riprel;
     {
       op_address[op_ad] = op;
       op_riprel[op_ad] = riprel;
@@ -3606,12 +4642,6 @@ OP_REG (int code, int sizeflag)
 
   switch (code)
     {
 
   switch (code)
     {
-    case indir_dx_reg:
-      if (intel_syntax)
-       s = "[dx]";
-      else
-       s = "(%dx)";
-      break;
     case ax_reg: case cx_reg: case dx_reg: case bx_reg:
     case sp_reg: case bp_reg: case si_reg: case di_reg:
       s = names16[code - ax_reg + add];
     case ax_reg: case cx_reg: case dx_reg: case bx_reg:
     case sp_reg: case bp_reg: case si_reg: case di_reg:
       s = names16[code - ax_reg + add];
@@ -3630,7 +4660,7 @@ OP_REG (int code, int sizeflag)
       break;
     case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
     case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
       break;
     case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
     case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
-      if (mode_64bit)
+      if (address_mode == mode_64bit && (sizeflag & DFLAG))
        {
          s = names64[code - rAX_reg + add];
          break;
        {
          s = names64[code - rAX_reg + add];
          break;
@@ -3664,7 +4694,7 @@ OP_IMREG (int code, int sizeflag)
     {
     case indir_dx_reg:
       if (intel_syntax)
     {
     case indir_dx_reg:
       if (intel_syntax)
-       s = "[dx]";
+       s = "dx";
       else
        s = "(%dx)";
       break;
       else
        s = "(%dx)";
       break;
@@ -3695,6 +4725,14 @@ OP_IMREG (int code, int sizeflag)
        s = names16[code - eAX_reg];
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
        s = names16[code - eAX_reg];
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
+    case z_mode_ax_reg:
+      if ((rex & REX_MODE64) || (sizeflag & DFLAG))
+       s = *names32;
+      else
+       s = *names16;
+      if (!(rex & REX_MODE64))
+       used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
     default:
       s = INTERNAL_DISASSEMBLER_ERROR;
       break;
     default:
       s = INTERNAL_DISASSEMBLER_ERROR;
       break;
@@ -3716,7 +4754,7 @@ OP_I (int bytemode, int sizeflag)
       mask = 0xff;
       break;
     case q_mode:
       mask = 0xff;
       break;
     case q_mode:
-      if (mode_64bit)
+      if (address_mode == mode_64bit)
        {
          op = get32s ();
          break;
        {
          op = get32s ();
          break;
@@ -3764,7 +4802,7 @@ OP_I64 (int bytemode, int sizeflag)
   bfd_signed_vma op;
   bfd_signed_vma mask = -1;
 
   bfd_signed_vma op;
   bfd_signed_vma mask = -1;
 
-  if (!mode_64bit)
+  if (address_mode != mode_64bit)
     {
       OP_I (bytemode, sizeflag);
       return;
     {
       OP_I (bytemode, sizeflag);
       return;
@@ -3863,6 +4901,7 @@ OP_J (int bytemode, int sizeflag)
 {
   bfd_vma disp;
   bfd_vma mask = -1;
 {
   bfd_vma disp;
   bfd_vma mask = -1;
+  bfd_vma segment = 0;
 
   switch (bytemode)
     {
 
   switch (bytemode)
     {
@@ -3873,31 +4912,41 @@ OP_J (int bytemode, int sizeflag)
        disp -= 0x100;
       break;
     case v_mode:
        disp -= 0x100;
       break;
     case v_mode:
-      if (sizeflag & DFLAG)
+      if ((sizeflag & DFLAG) || (rex & REX_MODE64))
        disp = get32s ();
       else
        {
          disp = get16 ();
        disp = get32s ();
       else
        {
          disp = get16 ();
-         /* For some reason, a data16 prefix on a jump instruction
-            means that the pc is masked to 16 bits after the
-            displacement is added!  */
+         if ((disp & 0x8000) != 0)
+           disp -= 0x10000;
+         /* In 16bit mode, address is wrapped around at 64k within
+            the same segment.  Otherwise, a data16 prefix on a jump
+            instruction means that the pc is masked to 16 bits after
+            the displacement is added!  */
          mask = 0xffff;
          mask = 0xffff;
+         if ((prefixes & PREFIX_DATA) == 0)
+           segment = ((start_pc + codep - start_codep)
+                      & ~((bfd_vma) 0xffff));
        }
        }
+      used_prefixes |= (prefixes & PREFIX_DATA);
       break;
     default:
       oappend (INTERNAL_DISASSEMBLER_ERROR);
       return;
     }
       break;
     default:
       oappend (INTERNAL_DISASSEMBLER_ERROR);
       return;
     }
-  disp = (start_pc + codep - start_codep + disp) & mask;
+  disp = ((start_pc + codep - start_codep + disp) & mask) | segment;
   set_op (disp, 0);
   print_operand_value (scratchbuf, 1, disp);
   oappend (scratchbuf);
 }
 
 static void
   set_op (disp, 0);
   print_operand_value (scratchbuf, 1, disp);
   oappend (scratchbuf);
 }
 
 static void
-OP_SEG (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+OP_SEG (int bytemode, int sizeflag)
 {
 {
-  oappend (names_seg[reg]);
+  if (bytemode == w_mode)
+    oappend (names_seg[reg]);
+  else
+    OP_E (mod == 3 ? bytemode : w_mode, sizeflag);
 }
 
 static void
 }
 
 static void
@@ -3932,7 +4981,7 @@ OP_OFF (int bytemode, int sizeflag)
     intel_operand_size (bytemode, sizeflag);
   append_seg ();
 
     intel_operand_size (bytemode, sizeflag);
   append_seg ();
 
-  if ((sizeflag & AFLAG) || mode_64bit)
+  if ((sizeflag & AFLAG) || address_mode == mode_64bit)
     off = get32 ();
   else
     off = get16 ();
     off = get32 ();
   else
     off = get16 ();
@@ -3955,7 +5004,8 @@ OP_OFF64 (int bytemode, int sizeflag)
 {
   bfd_vma off;
 
 {
   bfd_vma off;
 
-  if (!mode_64bit)
+  if (address_mode != mode_64bit
+      || (prefixes & PREFIX_ADDR))
     {
       OP_OFF (bytemode, sizeflag);
       return;
     {
       OP_OFF (bytemode, sizeflag);
       return;
@@ -3987,7 +5037,7 @@ ptr_reg (int code, int sizeflag)
 
   *obufp++ = open_char;
   used_prefixes |= (prefixes & PREFIX_ADDR);
 
   *obufp++ = open_char;
   used_prefixes |= (prefixes & PREFIX_ADDR);
-  if (mode_64bit)
+  if (address_mode == mode_64bit)
     {
       if (!(sizeflag & AFLAG))
        s = names32[code - eAX_reg];
     {
       if (!(sizeflag & AFLAG))
        s = names32[code - eAX_reg];
@@ -4007,7 +5057,22 @@ static void
 OP_ESreg (int code, int sizeflag)
 {
   if (intel_syntax)
 OP_ESreg (int code, int sizeflag)
 {
   if (intel_syntax)
-    intel_operand_size (codep[-1] & 1 ? v_mode : b_mode, sizeflag);
+    {
+      switch (codep[-1])
+       {
+       case 0x6d:      /* insw/insl */
+         intel_operand_size (z_mode, sizeflag);
+         break;
+       case 0xa5:      /* movsw/movsl/movsq */
+       case 0xa7:      /* cmpsw/cmpsl/cmpsq */
+       case 0xab:      /* stosw/stosl */
+       case 0xaf:      /* scasw/scasl */
+         intel_operand_size (v_mode, sizeflag);
+         break;
+       default:
+         intel_operand_size (b_mode, sizeflag);
+       }
+    }
   oappend ("%es:" + intel_syntax);
   ptr_reg (code, sizeflag);
 }
   oappend ("%es:" + intel_syntax);
   ptr_reg (code, sizeflag);
 }
@@ -4016,10 +5081,21 @@ static void
 OP_DSreg (int code, int sizeflag)
 {
   if (intel_syntax)
 OP_DSreg (int code, int sizeflag)
 {
   if (intel_syntax)
-    intel_operand_size (codep[-1] != 0xd7 && (codep[-1] & 1)
-                       ? v_mode
-                       : b_mode,
-                       sizeflag);
+    {
+      switch (codep[-1])
+       {
+       case 0x6f:      /* outsw/outsl */
+         intel_operand_size (z_mode, sizeflag);
+         break;
+       case 0xa5:      /* movsw/movsl/movsq */
+       case 0xa7:      /* cmpsw/cmpsl/cmpsq */
+       case 0xad:      /* lodsw/lodsl/lodsq */
+         intel_operand_size (v_mode, sizeflag);
+         break;
+       default:
+         intel_operand_size (b_mode, sizeflag);
+       }
+    }
   if ((prefixes
        & (PREFIX_CS
          | PREFIX_DS
   if ((prefixes
        & (PREFIX_CS
          | PREFIX_DS
@@ -4041,7 +5117,7 @@ OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
       USED_REX (REX_EXTX);
       add = 8;
     }
       USED_REX (REX_EXTX);
       add = 8;
     }
-  else if (!mode_64bit && (prefixes & PREFIX_LOCK))
+  else if (address_mode != mode_64bit && (prefixes & PREFIX_LOCK))
     {
       used_prefixes |= PREFIX_LOCK;
       add = 8;
     {
       used_prefixes |= PREFIX_LOCK;
       add = 8;
@@ -4140,6 +5216,41 @@ OP_EM (int bytemode, int sizeflag)
   oappend (scratchbuf + intel_syntax);
 }
 
   oappend (scratchbuf + intel_syntax);
 }
 
+/* cvt* are the only instructions in sse2 which have 
+   both SSE and MMX operands and also have 0x66 prefix 
+   in their opcode. 0x66 was originally used to differentiate 
+   between SSE and MMX instruction(operands). So we have to handle the 
+   cvt* separately using OP_EMC and OP_MXC */
+static void
+OP_EMC (int bytemode, int sizeflag)
+{
+  if (mod != 3)
+    {
+      if (intel_syntax && bytemode == v_mode)
+       {
+         bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode;
+         used_prefixes |= (prefixes & PREFIX_DATA);
+       }
+      OP_E (bytemode, sizeflag);
+      return;
+    }
+  
+  /* Skip mod/rm byte.  */
+  MODRM_CHECK;
+  codep++;
+  used_prefixes |= (prefixes & PREFIX_DATA);
+  sprintf (scratchbuf, "%%mm%d", rm);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_MXC (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  used_prefixes |= (prefixes & PREFIX_DATA);
+  sprintf (scratchbuf, "%%mm%d", reg);
+  oappend (scratchbuf + intel_syntax);
+}
+
 static void
 OP_EX (int bytemode, int sizeflag)
 {
 static void
 OP_EX (int bytemode, int sizeflag)
 {
@@ -4193,7 +5304,8 @@ static void
 OP_M (int bytemode, int sizeflag)
 {
   if (mod == 3)
 OP_M (int bytemode, int sizeflag)
 {
   if (mod == 3)
-    BadOp ();  /* bad lea,lds,les,lfs,lgs,lss modrm */
+    /* bad bound,lea,lds,les,lfs,lgs,lss,cmpxchg8b,vmptrst modrm */
+    BadOp ();
   else
     OP_E (bytemode, sizeflag);
 }
   else
     OP_E (bytemode, sizeflag);
 }
@@ -4230,12 +5342,29 @@ OP_0fae (int bytemode, int sizeflag)
   OP_E (bytemode, sizeflag);
 }
 
   OP_E (bytemode, sizeflag);
 }
 
+/* NOP is an alias of "xchg %ax,%ax" in 16bit mode, "xchg %eax,%eax" in
+   32bit mode and "xchg %rax,%rax" in 64bit mode.  NOP with REPZ prefix
+   is called PAUSE.  We display "xchg %ax,%ax" instead of "data16 nop".
+ */
+
 static void
 static void
-NOP_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+NOP_Fixup1 (int bytemode, int sizeflag)
 {
 {
-  /* NOP with REPZ prefix is called PAUSE.  */
   if (prefixes == PREFIX_REPZ)
     strcpy (obuf, "pause");
   if (prefixes == PREFIX_REPZ)
     strcpy (obuf, "pause");
+  else if (prefixes == PREFIX_DATA
+          || ((rex & REX_MODE64) && rex != 0x48))
+    OP_REG (bytemode, sizeflag);
+  else
+    strcpy (obuf, "nop");
+}
+
+static void
+NOP_Fixup2 (int bytemode, int sizeflag)
+{
+  if (prefixes == PREFIX_DATA
+      || ((rex & REX_MODE64) && rex != 0x48))
+    OP_IMREG (bytemode, sizeflag);
 }
 
 static const char *const Suffix3DNow[] = {
 }
 
 static const char *const Suffix3DNow[] = {
@@ -4403,18 +5532,31 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
   if (mod == 3 && reg == 1 && rm <= 1)
     {
       /* Override "sidt".  */
   if (mod == 3 && reg == 1 && rm <= 1)
     {
       /* Override "sidt".  */
-      char *p = obuf + strlen (obuf) - 4;
+      size_t olen = strlen (obuf);
+      char *p = obuf + olen - 4;
+      const char **names = (address_mode == mode_64bit
+                           ? names64 : names32);
 
       /* We might have a suffix when disassembling with -Msuffix.  */
       if (*p == 'i')
        --p;
 
 
       /* We might have a suffix when disassembling with -Msuffix.  */
       if (*p == 'i')
        --p;
 
+      /* Remove "addr16/addr32" if we aren't in Intel mode.  */
+      if (!intel_syntax
+         && (prefixes & PREFIX_ADDR)
+         && olen >= (4 + 7)
+         && *(p - 1) == ' '
+         && CONST_STRNEQ (p - 7, "addr")
+         && (CONST_STRNEQ (p - 3, "16")
+             || CONST_STRNEQ (p - 3, "32")))
+       p -= 7;
+
       if (rm)
        {
          /* mwait %eax,%ecx  */
          strcpy (p, "mwait");
          if (!intel_syntax)
       if (rm)
        {
          /* mwait %eax,%ecx  */
          strcpy (p, "mwait");
          if (!intel_syntax)
-           strcpy (op1out, names32[0]);
+           strcpy (op1out, names[0]);
        }
       else
        {
        }
       else
        {
@@ -4422,21 +5564,23 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
          strcpy (p, "monitor");
          if (!intel_syntax)
            {
          strcpy (p, "monitor");
          if (!intel_syntax)
            {
-             if (!mode_64bit)
-               strcpy (op1out, names32[0]);
-             else if (!(prefixes & PREFIX_ADDR))
-               strcpy (op1out, names64[0]);
+             const char **op1_names;
+             if (!(prefixes & PREFIX_ADDR))
+               op1_names = (address_mode == mode_16bit
+                            ? names16 : names);
              else
                {
              else
                {
-                 strcpy (op1out, names32[0]);
+                 op1_names = (address_mode != mode_32bit
+                              ? names32 : names16);
                  used_prefixes |= PREFIX_ADDR;
                }
                  used_prefixes |= PREFIX_ADDR;
                }
-             strcpy (op3out, names32[2]);
+             strcpy (op1out, op1_names[0]);
+             strcpy (op3out, names[2]);
            }
        }
       if (!intel_syntax)
        {
            }
        }
       if (!intel_syntax)
        {
-         strcpy (op2out, names32[1]);
+         strcpy (op2out, names[1]);
          two_source_ops = 1;
        }
 
          two_source_ops = 1;
        }
 
@@ -4504,7 +5648,7 @@ SVME_Fixup (int bytemode, int sizeflag)
     case 0xda:
     case 0xdb:
       *obufp++ = open_char;
     case 0xda:
     case 0xdb:
       *obufp++ = open_char;
-      if (mode_64bit || (sizeflag & AFLAG))
+      if (address_mode == mode_64bit || (sizeflag & AFLAG))
         alt = names32[0];
       else
         alt = names16[0];
         alt = names32[0];
       else
         alt = names16[0];
@@ -4546,55 +5690,6 @@ BadOp (void)
   oappend ("(bad)");
 }
 
   oappend ("(bad)");
 }
 
-static void
-SEG_Fixup (int extrachar, int sizeflag)
-{
-  if (mod == 3)
-    {
-      /* We need to add a proper suffix with
-
-               movw %ds,%ax
-               movl %ds,%eax
-               movq %ds,%rax
-               movw %ax,%ds
-               movl %eax,%ds
-               movq %rax,%ds
-       */
-      const char *suffix;
-
-      if (prefixes & PREFIX_DATA)
-       suffix = "w";
-      else
-       {
-         USED_REX (REX_MODE64);
-         if (rex & REX_MODE64)
-           suffix = "q";
-         else
-           suffix = "l";
-       }
-      strcat (obuf, suffix);
-    }
-  else
-    {
-      /* We need to fix the suffix for
-
-               movw %ds,(%eax)
-               movw %ds,(%rax)
-               movw (%eax),%ds
-               movw (%rax),%ds
-
-        Override "mov[l|q]".  */
-      char *p = obuf + strlen (obuf) - 1;
-
-      /* We might not have a suffix.  */
-      if (*p == 'v')
-       ++p;
-      *p = 'w';
-    }
-
-  OP_E (extrachar, sizeflag);
-}
-
 static void
 VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
 {
 static void
 VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
 {
@@ -4641,3 +5736,90 @@ OP_VMX (int bytemode, int sizeflag)
     strcpy (obuf, "vmptrld");
   OP_E (bytemode, sizeflag);
 }
     strcpy (obuf, "vmptrld");
   OP_E (bytemode, sizeflag);
 }
+
+static void
+REP_Fixup (int bytemode, int sizeflag)
+{
+  /* The 0xf3 prefix should be displayed as "rep" for ins, outs, movs,
+     lods and stos.  */
+  size_t ilen = 0;
+
+  if (prefixes & PREFIX_REPZ)
+    switch (*insn_codep) 
+      {
+      case 0x6e:       /* outsb */
+      case 0x6f:       /* outsw/outsl */
+      case 0xa4:       /* movsb */
+      case 0xa5:       /* movsw/movsl/movsq */
+       if (!intel_syntax)
+         ilen = 5;
+       else
+         ilen = 4;
+       break;
+      case 0xaa:       /* stosb */
+      case 0xab:       /* stosw/stosl/stosq */
+      case 0xac:       /* lodsb */
+      case 0xad:       /* lodsw/lodsl/lodsq */
+       if (!intel_syntax && (sizeflag & SUFFIX_ALWAYS))
+         ilen = 5;
+       else
+         ilen = 4;
+       break;
+      case 0x6c:       /* insb */
+      case 0x6d:       /* insl/insw */
+       if (!intel_syntax)
+         ilen = 4;
+       else
+         ilen = 3;
+       break;
+      default:
+       abort ();
+       break;
+      }
+
+  if (ilen != 0)
+    {
+      size_t olen;
+      char *p;
+
+      olen = strlen (obuf);
+      p = obuf + olen - ilen - 1 - 4;
+      /* Handle "repz [addr16|addr32]".  */
+      if ((prefixes & PREFIX_ADDR))
+       p -= 1 + 6;
+
+      memmove (p + 3, p + 4, olen - (p + 3 - obuf));
+    }
+
+  switch (bytemode)
+    {
+    case al_reg:
+    case eAX_reg:
+    case indir_dx_reg:
+      OP_IMREG (bytemode, sizeflag);
+      break;
+    case eDI_reg:
+      OP_ESreg (bytemode, sizeflag);
+      break;
+    case eSI_reg:
+      OP_DSreg (bytemode, sizeflag);
+      break;
+    default:
+      abort ();
+      break;
+    }
+}
+
+static void
+CMPXCHG8B_Fixup (int bytemode, int sizeflag)
+{
+  USED_REX (REX_MODE64);
+  if (rex & REX_MODE64)
+    {
+      /* Change cmpxchg8b to cmpxchg16b.  */
+      char *p = obuf + strlen (obuf) - 2;
+      strcpy (p, "16b");
+      bytemode = o_mode;
+    }
+  OP_M (bytemode, sizeflag);
+}
This page took 0.101744 seconds and 4 git commands to generate.