* i386-dis.c (FWAIT_OPCODE): Define.
authorIan Lance Taylor <ian@airs.com>
Sun, 13 Jun 1999 13:56:26 +0000 (13:56 +0000)
committerIan Lance Taylor <ian@airs.com>
Sun, 13 Jun 1999 13:56:26 +0000 (13:56 +0000)
(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.

opcodes/ChangeLog
opcodes/i386-dis.c

index 1e393c2..cf5ab79 100644 (file)
@@ -1,3 +1,14 @@
+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.
index 7cda14e..b534698 100644 (file)
@@ -47,7 +47,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define UNIXWARE_COMPAT 1
 #endif
 
-
 static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
 
 struct dis_private
@@ -59,6 +58,27 @@ 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.  */
@@ -81,7 +101,16 @@ fetch_data (info, addr)
                                      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
@@ -1848,21 +1877,6 @@ static const struct dis386 prefix_user_table[][2] = {
 
 #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 ()
 {
@@ -1905,7 +1919,7 @@ 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.  */
@@ -2008,9 +2022,6 @@ print_insn_i386 (pc, info)
   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;
@@ -2024,6 +2035,34 @@ print_insn_i386 (pc, info)
   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;