Disassembly of section .text:
 
-0+000 <foo>:
-   0:  9b 26 67 d9 3c[         ]+fstcw[        ]+%es:\(%si\)
-   5:  9b df e0 [      ]*fstsw  %ax
-   8:  9b df e0 [      ]*fstsw  %ax
-   b:  9b 67 df e0 [   ]*addr16 fstsw %ax
-   f:  36 67 66 f3 a7 [        ]*repz cmpsw %es:\(%di\),%ss:\(%si\)
-  14:  26 9b[  ]*es fwait
+0+ <foo>:
+[      ]*[a-f0-9]+:    9b 26 67 d9 3c          fstcw  %es:\(%si\)
+[      ]*[a-f0-9]+:    9b df e0                fstsw  %ax
+[      ]*[a-f0-9]+:    9b df e0                fstsw  %ax
+[      ]*[a-f0-9]+:    9b 67 df e0             addr16 fstsw %ax
+[      ]*[a-f0-9]+:    36 67 66 f3 a7          repz cmpsw %es:\(%di\),%ss:\(%si\)
+[      ]*[a-f0-9]+:    26 9b                   es fwait
+[      ]*[a-f0-9]+:    66 f2 0f 38 17          data16 \(bad\) 
+[      ]*[a-f0-9]+:    f2 66 0f 54             repnz \(bad\)
+[      ]*[a-f0-9]+:    f2 0f 54                repnz \(bad\)
+[      ]*[a-f0-9]+:    f2 66 0f 11 22          data16 movsd %xmm4,\(%edx\)
+[      ]*[a-f0-9]+:    f2 67 66 0f 11 22       data16 movsd %xmm4,\(%bp,%si\)
+[      ]*[a-f0-9]+:    f2 67 f0 66 0f 11 22    lock data16 movsd %xmm4,\(%bp,%si\)
+[      ]*[a-f0-9]+:    f3 66 0f 11 22          data16 movss %xmm4,\(%edx\)
+[      ]*[a-f0-9]+:    f3 67 f0 66 0f 11 22    lock data16 movss %xmm4,\(%bp,%si\)
+[      ]*[a-f0-9]+:    f3 67 f2 66 0f 11 22    repz data16 movsd %xmm4,\(%bp,%si\)
+[      ]*[a-f0-9]+:    f3 66 3e 0f 11 22       data16 movss %xmm4,%ds:\(%edx\)
+[      ]*[a-f0-9]+:    f2 66 36 0f 11 22       data16 movsd %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f3 f0 f2 66 36 0f 11 22         repz lock data16 movsd %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f2 66 3e 36 0f 11 22    data16 ds movsd %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f2 67 66 3e 36 0f 11 22         data16 ds movsd %xmm4,%ss:\(%bp,%si\)
+[      ]*[a-f0-9]+:    f2 67 f0 66 3e 36 0f 11 22      lock data16 ds movsd %xmm4,%ss:\(%bp,%si\)
+[      ]*[a-f0-9]+:    f3 66 3e 36 0f 11 22    data16 ds movss %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f3 f0 66 3e 36 0f 11 22         lock data16 ds movss %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f3 67 f2 66 3e 36 0f 11 22      repz data16 ds movsd %xmm4,%ss:\(%bp,%si\)
+[      ]*[a-f0-9]+:    f2 66 90                repnz xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 67 66 90             repnz addr16 xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 67 f0 66 90          repnz addr16 lock xchg %ax,%ax
+[      ]*[a-f0-9]+:    f3 66 90                data16 pause 
+[      ]*[a-f0-9]+:    f3 67 f0 66 90          addr16 lock data16 pause 
+[      ]*[a-f0-9]+:    f3 67 f2 66 90          repz addr16 repnz xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 3e 90                repnz ds nop
+[      ]*[a-f0-9]+:    f2 f0 67 3e 90          repnz lock addr16 ds nop
+[      ]*[a-f0-9]+:    f3 3e 90                ds pause 
+[      ]*[a-f0-9]+:    f3 66 3e 90             data16 ds pause 
+[      ]*[a-f0-9]+:    f3 f0 3e 90             lock ds pause 
+[      ]*[a-f0-9]+:    f3 f0 67 3e 90          lock addr16 ds pause 
+[      ]*[a-f0-9]+:    f3 f2 67 3e 90          repz repnz addr16 ds nop
+[      ]*[a-f0-9]+:    66 f0 36 90             lock ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 36 90                repnz ss nop
+[      ]*[a-f0-9]+:    f2 66 36 90             repnz ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 f0 36 90             repnz lock ss nop
+[      ]*[a-f0-9]+:    f2 f0 67 36 90          repnz lock addr16 ss nop
+[      ]*[a-f0-9]+:    f3 36 90                ss pause 
+[      ]*[a-f0-9]+:    f3 67 36 90             addr16 ss pause 
+[      ]*[a-f0-9]+:    f3 f0 67 36 90          lock addr16 ss pause 
+[      ]*[a-f0-9]+:    f3 f2 36 90             repz repnz ss nop
+[      ]*[a-f0-9]+:    f3 f2 67 36 90          repz repnz addr16 ss nop
+[      ]*[a-f0-9]+:    f3 f0 f2 66 36 90       repz lock repnz ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    66 3e 36 90             ds ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    67 66 3e 36 90          addr16 ds ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    67 f0 66 3e 36 90       addr16 lock ds ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    f3 66 3e 36 90          data16 ds ss pause 
+[      ]*[a-f0-9]+:    f3 f0 66 3e 36 90       lock data16 ds ss pause 
+[      ]*[a-f0-9]+:    f3 f2 67 3e 36 90       repz repnz addr16 ds ss nop
+[      ]*[a-f0-9]+:    f3 67 f2 66 3e 36 90    repz addr16 repnz ds ss xchg %ax,%ax
 #pass
 
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
 };
 
+static const unsigned char twobyte_has_mandatory_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,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,1,1,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 */ 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 */
+  /* 70 */ 1,0,0,0,1,1,1,1,0,0,1,1,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 */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,1,1,1,1,1,0,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 */
+  /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,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 *mnemonicendp;
 static unsigned char *start_codep;
 static unsigned char *insn_codep;
 static unsigned char *codep;
+static unsigned char *end_codep;
 static int last_lock_prefix;
 static int last_repz_prefix;
 static int last_repnz_prefix;
 static int last_addr_prefix;
 static int last_rex_prefix;
 static int last_seg_prefix;
+/* The PREFIX_REPZ/PREFIX_REPNZ/PREFIX_DATA prefix is mandatory.  */
+static int mandatory_prefix;
+/* The active segment register prefix.  */
+static int active_seg_prefix;
 #define MAX_CODE_LENGTH 15
 /* We can up to 14 prefixes since the maximum instruction length is
    15bytes.  */
   last_addr_prefix = -1;
   last_rex_prefix = -1;
   last_seg_prefix = -1;
+  active_seg_prefix = 0;
   for (i = 0; i < (int) ARRAY_SIZE (all_prefixes); i++)
     all_prefixes[i] = 0;
   i = 0;
        case 0x2e:
          prefixes |= PREFIX_CS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_CS;
          break;
        case 0x36:
          prefixes |= PREFIX_SS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_SS;
          break;
        case 0x3e:
          prefixes |= PREFIX_DS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_DS;
          break;
        case 0x26:
          prefixes |= PREFIX_ES;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_ES;
          break;
        case 0x64:
          prefixes |= PREFIX_FS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_FS;
          break;
        case 0x65:
          prefixes |= PREFIX_GS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_GS;
          break;
        case 0x66:
          prefixes |= PREFIX_DATA;
   return 0;
 }
 
-static int
-seg_prefix (int pref)
-{
-  switch (pref)
-    {
-    case 0x2e:
-      return PREFIX_CS;
-    case 0x36:
-      return PREFIX_SS;
-    case 0x3e:
-      return PREFIX_DS;
-    case 0x26:
-      return PREFIX_ES;
-    case 0x64:
-      return PREFIX_FS;
-    case 0x65:
-      return PREFIX_GS;
-    default:
-      return 0;
-    }
-}
-
 /* Return the name of the prefix byte PREF, or NULL if PREF is not a
    prefix byte.  */
 
        }
       else
        {
+         int last_prefix = -1;
+         int prefix = 0;
          vindex = 0;
-         used_prefixes |= (prefixes & PREFIX_REPZ);
-         if (prefixes & PREFIX_REPZ)
-           {
-             vindex = 1;
-             all_prefixes[last_repz_prefix] = 0;
-           }
-         else
+         /* We check PREFIX_REPNZ and PREFIX_REPZ before PREFIX_DATA.
+            When there are multiple PREFIX_REPNZ and PREFIX_REPZ, the
+            last one wins.  */
+         if ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) != 0)
            {
-             /* We should check PREFIX_REPNZ and PREFIX_REPZ before
-                PREFIX_DATA.  */
-             used_prefixes |= (prefixes & PREFIX_REPNZ);
-             if (prefixes & PREFIX_REPNZ)
+             if (last_repz_prefix > last_repnz_prefix)
                {
-                 vindex = 3;
-                 all_prefixes[last_repnz_prefix] = 0;
+                 vindex = 1;
+                 prefix = PREFIX_REPZ;
+                 last_prefix = last_repz_prefix;
                }
              else
                {
-                 used_prefixes |= (prefixes & PREFIX_DATA);
-                 if (prefixes & PREFIX_DATA)
-                   {
-                     vindex = 2;
-                     all_prefixes[last_data_prefix] = 0;
-                   }
+                 vindex = 3;
+                 prefix = PREFIX_REPNZ;
+                 last_prefix = last_repnz_prefix;
                }
+
+             /* Ignore the invalid index if it isn't mandatory.  */
+             if (!mandatory_prefix
+                 && (prefix_table[dp->op[1].bytemode][vindex].name
+                     == NULL)
+                 && (prefix_table[dp->op[1].bytemode][vindex].op[0].bytemode
+                     == 0))
+               vindex = 0;
+           }
+
+         if (vindex == 0 && (prefixes & PREFIX_DATA) != 0)
+           {
+             vindex = 2;
+             prefix = PREFIX_DATA;
+             last_prefix = last_data_prefix;
+           }
+
+         if (vindex != 0)
+           {
+             used_prefixes |= prefix;
+             all_prefixes[last_prefix] = 0;
            }
        }
       dp = &prefix_table[dp->op[1].bytemode][vindex];
       FETCH_DATA (info, codep + 2);
       vindex = *codep++;
       dp = &three_byte_table[dp->op[1].bytemode][vindex];
+      end_codep = codep;
       modrm.mod = (*codep >> 6) & 3;
       modrm.reg = (*codep >> 3) & 7;
       modrm.rm = *codep & 7;
       vindex = *codep++;
       dp = &xop_table[vex_table_index][vindex];
 
+      end_codep = codep;
       FETCH_DATA (info, codep + 1);
       modrm.mod = (*codep >> 6) & 3;
       modrm.reg = (*codep >> 3) & 7;
       codep++;
       vindex = *codep++;
       dp = &vex_table[vex_table_index][vindex];
+      end_codep = codep;
       /* There is no MODRM byte for VEX [82|77].  */
       if (vindex != 0x77 && vindex != 0x82)
        {
       codep++;
       vindex = *codep++;
       dp = &vex_table[dp->op[1].bytemode][vindex];
+      end_codep = codep;
       /* There is no MODRM byte for VEX [82|77].  */
       if (vindex != 0x77 && vindex != 0x82)
        {
       codep++;
       vindex = *codep++;
       dp = &evex_table[vex_table_index][vindex];
+      end_codep = codep;
       FETCH_DATA (info, codep + 1);
       modrm.mod = (*codep >> 6) & 3;
       modrm.reg = (*codep >> 3) & 7;
       threebyte = *++codep;
       dp = &dis386_twobyte[threebyte];
       need_modrm = twobyte_has_modrm[*codep];
+      mandatory_prefix = twobyte_has_mandatory_prefix[*codep];
       codep++;
     }
   else
     {
       dp = &dis386[*codep];
       need_modrm = onebyte_has_modrm[*codep];
+      mandatory_prefix = 0;
       codep++;
     }
 
-  if ((prefixes & PREFIX_REPZ))
-    used_prefixes |= PREFIX_REPZ;
-  if ((prefixes & PREFIX_REPNZ))
-    used_prefixes |= PREFIX_REPNZ;
-  if ((prefixes & PREFIX_LOCK))
-    used_prefixes |= PREFIX_LOCK;
-
   default_prefixes = 0;
   if (prefixes & PREFIX_ADDR)
     {
        }
     }
 
+  end_codep = codep;
   if (need_modrm)
     {
       FETCH_DATA (info, codep + 1);
        }
     }
 
-  /* See if any prefixes were not used.  If so, print the first one
-     separately.  If we don't do this, we'll wind up printing an
-     instruction stream which does not precisely correspond to the
-     bytes we are disassembling.  */
-  if ((prefixes & ~(used_prefixes | default_prefixes)) != 0)
-    {
-      for (i = 0; i < (int) ARRAY_SIZE (all_prefixes); i++)
-       if (all_prefixes[i])
-         {
-           const char *name;
-           name = prefix_name (all_prefixes[i], priv.orig_sizeflag);
-           if (name == NULL)
-             name = INTERNAL_DISASSEMBLER_ERROR;
-           (*info->fprintf_func) (info->stream, "%s", name);
-           return 1;
-         }
-    }
-
   /* Check if the REX prefix is used.  */
   if (rex_ignored == 0 && (rex ^ rex_used) == 0 && last_rex_prefix >= 0)
     all_prefixes[last_rex_prefix] = 0;
   /* Check if the SEG prefix is used.  */
   if ((prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES
                   | PREFIX_FS | PREFIX_GS)) != 0
-      && (used_prefixes
-         & seg_prefix (all_prefixes[last_seg_prefix])) != 0)
+      && (used_prefixes & active_seg_prefix) != 0)
     all_prefixes[last_seg_prefix] = 0;
 
   /* Check if the ADDR prefix is used.  */
       && (used_prefixes & PREFIX_ADDR) != 0)
     all_prefixes[last_addr_prefix] = 0;
 
-  /* Check if the DATA prefix is used.  */
-  if ((prefixes & PREFIX_DATA) != 0
-      && (used_prefixes & PREFIX_DATA) != 0)
-    all_prefixes[last_data_prefix] = 0;
+  /* Check if the DATA prefix is used.  Restore the DFLAG bit in
+     sizeflag if the DATA prefix is unused.  */
+  if ((prefixes & PREFIX_DATA) != 0)
+    {
+      if ((used_prefixes & PREFIX_DATA) != 0)
+       all_prefixes[last_data_prefix] = 0;
+      else if ((default_prefixes & PREFIX_DATA) == 0)
+       sizeflag ^= DFLAG;
+    }
 
   prefix_length = 0;
   for (i = 0; i < (int) ARRAY_SIZE (all_prefixes); i++)
        (*info->fprintf_func) (info->stream, "%s ", name);
       }
 
+  /* If the mandatory PREFIX_REPZ/PREFIX_REPNZ/PREFIX_DATA prefix is
+     unused, opcode is invalid.  Since the PREFIX_DATA prefix may be
+     used by putop and MMX/SSE operand and may be overriden by the
+     PREFIX_REPZ/PREFIX_REPNZ fix, we check the PREFIX_DATA prefix
+     separately.  */
+  if (mandatory_prefix
+      && dp != &bad_opcode
+      && (((prefixes
+           & (PREFIX_REPZ | PREFIX_REPNZ)) != 0
+          && (used_prefixes
+              & (PREFIX_REPZ | PREFIX_REPNZ)) == 0)
+         || ((((prefixes
+                & (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA))
+               == PREFIX_DATA)
+              && (used_prefixes & PREFIX_DATA) == 0))))
+    {
+      (*info->fprintf_func) (info->stream, "(bad)");
+      return end_codep - priv.the_buffer;
+    }
+
   /* Check maximum code length.  */
   if ((codep - start_codep) > MAX_CODE_LENGTH)
     {
 static void
 append_seg (void)
 {
-  if (prefixes & PREFIX_CS)
+  /* Only print the active segment register.  */
+  if (!active_seg_prefix)
+    return;
+
+  used_prefixes |= active_seg_prefix;
+  switch (active_seg_prefix)
     {
-      used_prefixes |= PREFIX_CS;
+    case PREFIX_CS:
       oappend_maybe_intel ("%cs:");
-    }
-  if (prefixes & PREFIX_DS)
-    {
-      used_prefixes |= PREFIX_DS;
+      break;
+    case PREFIX_DS:
       oappend_maybe_intel ("%ds:");
-    }
-  if (prefixes & PREFIX_SS)
-    {
-      used_prefixes |= PREFIX_SS;
+      break;
+    case PREFIX_SS:
       oappend_maybe_intel ("%ss:");
-    }
-  if (prefixes & PREFIX_ES)
-    {
-      used_prefixes |= PREFIX_ES;
+      break;
+    case PREFIX_ES:
       oappend_maybe_intel ("%es:");
-    }
-  if (prefixes & PREFIX_FS)
-    {
-      used_prefixes |= PREFIX_FS;
+      break;
+    case PREFIX_FS:
       oappend_maybe_intel ("%fs:");
-    }
-  if (prefixes & PREFIX_GS)
-    {
-      used_prefixes |= PREFIX_GS;
+      break;
+    case PREFIX_GS:
       oappend_maybe_intel ("%gs:");
+      break;
+    default:
+      break;
     }
 }
 
        {
          if (modrm.mod != 0 || base == 5)
            {
-             if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
-                             | PREFIX_ES | PREFIX_FS | PREFIX_GS))
-               ;
-             else
+             if (!active_seg_prefix)
                {
                  oappend (names_seg[ds_reg - es_reg]);
                  oappend (":");
        }
       else if (intel_syntax)
        {
-         if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
-                         | PREFIX_ES | PREFIX_FS | PREFIX_GS))
-           ;
-         else
+         if (!active_seg_prefix)
            {
              oappend (names_seg[ds_reg - es_reg]);
              oappend (":");
 
   if (intel_syntax)
     {
-      if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
-                       | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+      if (!active_seg_prefix)
        {
          oappend (names_seg[ds_reg - es_reg]);
          oappend (":");
 
   if (intel_syntax)
     {
-      if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
-                       | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+      if (!active_seg_prefix)
        {
          oappend (names_seg[ds_reg - es_reg]);
          oappend (":");
          intel_operand_size (b_mode, sizeflag);
        }
     }
-  if ((prefixes
-       & (PREFIX_CS
-         | PREFIX_DS
-         | PREFIX_SS
-         | PREFIX_ES
-         | PREFIX_FS
-         | PREFIX_GS)) == 0)
-    prefixes |= PREFIX_DS;
+  /* Set active_seg_prefix to PREFIX_DS if it is unset so that the
+     default segment register DS is printed.  */
+  if (!active_seg_prefix)
+    active_seg_prefix = PREFIX_DS;
   append_seg ();
   ptr_reg (code, sizeflag);
 }