+1999-06-13  Ian Lance Taylor  <ian@zembu.com>
+
+       * i386-dis.c (FWAIT_OPCODE): Define.
+       (fetch_data): Don't print an error message if we have already
+       found an fwait prefix.
+       (ckprefix): Use FWAIT_OPCODE rather than 0x9b.
+       (print_insn_i386): If setjmp fails, indicating a data error, but
+       we have found an fwait prefix, then print it as an fwait
+       instruction.  In any case, return the number of bytes consumed, if
+       any, rather than always returning -1.
+
 1999-06-07  Jakub Jelinek  <jj@ultra.linux.cz>
 
        * sparc-opc.c: Fix up set, setsw, setuw operand kinds.
 
 #define UNIXWARE_COMPAT 1
 #endif
 
-
 static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
 
 struct dis_private
   jmp_buf bailout;
 };
 
+/* The opcode for the fwait instruction, which we treat as a prefix
+   when we can.  */
+#define FWAIT_OPCODE (0x9b)
+
+/* Flags for the prefixes for the current instruction.  See below.  */
+static int prefixes;
+
+/* Flags stored in PREFIXES.  */
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADDR 0x400
+#define PREFIX_FWAIT 0x800
+
 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
    on error.  */
                                      info);
   if (status != 0)
     {
-      (*info->memory_error_func) (status, start, info);
+      /* If we have found an fwait prefix and an fwait opcode, then
+        print_insn_i386 will arrange to print an instruction after we
+        longjmp, and we don't want to print an error message here.
+        This hack is required because we treat fwait as a prefix, but
+        since fwait is really an instruction we want to print a
+        standalone fwait correctly.  */
+      if ((prefixes & PREFIX_FWAIT) == 0
+         || memchr (priv->the_buffer, FWAIT_OPCODE,
+                    priv->max_fetched - priv->the_buffer) == NULL)
+       (*info->memory_error_func) (status, start, info);
       longjmp (priv->bailout, 1);
     }
   else
 
 #define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
 
-#define PREFIX_REPZ 1
-#define PREFIX_REPNZ 2
-#define PREFIX_LOCK 4
-#define PREFIX_CS 8
-#define PREFIX_SS 0x10
-#define PREFIX_DS 0x20
-#define PREFIX_ES 0x40
-#define PREFIX_FS 0x80
-#define PREFIX_GS 0x100
-#define PREFIX_DATA 0x200
-#define PREFIX_ADDR 0x400
-#define PREFIX_FWAIT 0x800
-
-static int prefixes;
-
 static void
 ckprefix ()
 {
        case 0x67:
          prefixes |= PREFIX_ADDR;
          break;
-       case 0x9b:
+       case FWAIT_OPCODE:
          /* fwait is really an instruction.  If there are prefixes
             before the fwait, they belong to the fwait, *not* to the
             following instruction.  */
   info->private_data = (PTR) &priv;
   priv.max_fetched = priv.the_buffer;
   priv.insn_start = pc;
-  if (setjmp (priv.bailout) != 0)
-    /* Error return.  */
-    return -1;
 
   obuf[0] = 0;
   op1out[0] = 0;
   start_codep = inbuf;
   codep = inbuf;
 
+  if (setjmp (priv.bailout) != 0)
+    {
+      /* Getting here means we tried for data but didn't get it.  That
+         means we have an incomplete instruction of some sort.
+         However, we need to check at least one case here: fwait is a
+         complete instruction, although we treat it as a prefix.  */
+      if (prefixes & PREFIX_FWAIT)
+       {
+         unsigned char *p;
+
+         p = memchr (inbuf, FWAIT_OPCODE, codep - inbuf);
+         if (p != NULL)
+           {
+             (*info->fprintf_func) (info->stream, "fwait");
+             return (p + 1) - inbuf;
+           }
+       }
+
+      if (codep > inbuf)
+       {
+         /* This will at least let objdump print the bytes followed
+             by the error message generated by fetch_data.  */
+         return codep - inbuf;
+       }
+
+      return -1;
+    }
+
   ckprefix ();
 
   insn_codep = codep;