provide a new interface (using read_memory_func) to call the disassemblers
authorJim Kingdon <jkingdon@engr.sgi.com>
Wed, 31 Mar 1993 21:43:25 +0000 (21:43 +0000)
committerJim Kingdon <jkingdon@engr.sgi.com>
Wed, 31 Mar 1993 21:43:25 +0000 (21:43 +0000)
which copes with errors in a plausible way

18 files changed:
binutils/ChangeLog
binutils/objdump.c
gdb/ChangeLog
gdb/core.c
gdb/h8500-tdep.c
gdb/i386-pinsn.c
gdb/m68k-pinsn.c
gdb/mips-pinsn.c
gdb/z8k-tdep.c
include/ChangeLog
include/dis-asm.h
opcodes/ChangeLog
opcodes/Makefile.in
opcodes/h8500-dis.c [new file with mode: 0644]
opcodes/i386-dis.c [new file with mode: 0644]
opcodes/m68k-dis.c [new file with mode: 0644]
opcodes/mips-dis.c
opcodes/z8k-dis.c

index a9a0b7b329f45214d0d394dc4fe89a35a2900d39..0e6dd4635b22a699be6bfaea5b18697f2225576b 100644 (file)
@@ -1,3 +1,7 @@
+Wed Mar 31 10:25:29 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * objdump.c (disassemble_data): Use new read_memory_func stuff.
+
 Thu Mar 25 10:38:11 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
 
        * objdump.c (fprintf): Declaration of variadic function had better
index 95f3a33717f88986e8e4242719c30e652c62ed71..7d36ad0ad21f0f52c6c29e218138cf64f770a9cb 100644 (file)
@@ -440,8 +440,12 @@ disassemble_data (abfd)
 
          bfd_get_section_contents (abfd, section, data, 0, bfd_get_section_size_before_reloc (section));
 
+         disasm_info.buffer = data;
+         disasm_info.buffer_vma = section->vma;
+         disasm_info.buffer_length =
+           bfd_get_section_size_before_reloc (section);
          i = 0;
-         while (i < bfd_get_section_size_before_reloc (section))
+         while (i < disasm_info.buffer_length)
            {
              if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 &&
                  data[i + 3] == 0)
@@ -489,9 +493,13 @@ disassemble_data (abfd)
                  printf (" ");
 
                  if (disassemble) /* New style */
-                   i += (*disassemble)(section->vma + i,
-                                       data + i,
-                                       &disasm_info);
+                   {
+                     int bytes = (*disassemble)(section->vma + i,
+                                                &disasm_info);
+                     if (bytes < 0)
+                       break;
+                     i += bytes;
+                   }
                  else /* Old style */
                    i += print (section->vma + i,
                                data + i,
index d423e55634c4a2a7e69693457175433064c2f713..44f8877a7dec2292fcdf09d105bdb7a0feceb012 100644 (file)
@@ -1,3 +1,9 @@
+Wed Mar 31 12:52:12 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * core.c (dis_asm_{read_memory,memory_error}): New functions.
+       m68k-pinsn.c, h8500-tdep.c, i386-pinsn.c, mips-pinsn.c, z8k-tdep.c:
+       Use read_memory_func interface to disassembler.
+
 Tue Mar 30 15:46:14 1993  K. Richard Pixley  (rich@rtl.cygnus.com)
 
        Teach sparc solaris to next over shared library functions.
index ca52e39af10a097b1df0906d94e05d207a258f40..a357352f8de9728b57f29cfac48e0f0baa659b1c 100644 (file)
@@ -28,6 +28,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "bfd.h"
 #include "target.h"
 #include "gdbcore.h"
+#include "dis-asm.h"
 
 extern char registers[];
 
@@ -160,6 +161,27 @@ read_memory (memaddr, myaddr, len)
     memory_error (status, memaddr);
 }
 
+/* Like target_read_memory, but slightly different parameters.  */
+int
+dis_asm_read_memory (memaddr, myaddr, len, info)
+     bfd_vma memaddr;
+     bfd_byte *myaddr;
+     int len;
+     disassemble_info *info;
+{
+  return target_read_memory (memaddr, myaddr, len);
+}
+
+/* Like memory_error with slightly different parameters.  */
+void
+dis_asm_memory_error (status, memaddr, info)
+     int status;
+     bfd_vma memaddr;
+     disassemble_info *info;
+{
+  memory_error (status, memaddr);
+}
+
 /* Same as target_write_memory, but report an error if can't write.  */
 void
 write_memory (memaddr, myaddr, len)
index 50d5ae055a1b201766db424258e077cabd88bdc4..fc16764806259129b4e56b019fd81f07459e3ae6 100644 (file)
@@ -110,12 +110,9 @@ print_insn (memaddr, stream)
      CORE_ADDR memaddr;
      FILE *stream;
 {
-  /* Nothing is bigger than 8 bytes */
-  char data[8];
   disassemble_info info;
-  read_memory (memaddr, data, sizeof (data));
   GDB_INIT_DISASSEMBLE_INFO(info, stream);
-  return print_insn_h8500 (memaddr, data, &info);
+  return print_insn_h8500 (memaddr, &info);
 }
 
 /* Given a GDB frame, determine the address of the calling function's frame.
index 6c88de9100aa2097dad91054f87d4b9abd1427ee..b6d7fe91e39f4855bbbb8e8456a4f6c41dff69a1 100644 (file)
@@ -20,9 +20,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "defs.h"
 #include "dis-asm.h"
 
-#define MAXLEN 20
 \f
-/* Print the m68k instruction at address MEMADDR in debugged memory,
+/* Print the instruction at address MEMADDR in debugged memory,
    on STREAM.  Returns length of the instruction, in bytes.  */
 
 int
@@ -30,16 +29,9 @@ print_insn (memaddr, stream)
      CORE_ADDR memaddr;
      FILE *stream;
 {
-  unsigned char buffer[MAXLEN];
-  register int i;
-  register unsigned char *p;
-  register char *d;
-  register int bestmask;
-  int best;
   disassemble_info info;
 
   GDB_INIT_DISASSEMBLE_INFO(info, stream);
 
-  read_memory (memaddr, (char *) buffer, MAXLEN);
-  return print_insn_i386 (memaddr, buffer, &info);
+  return print_insn_i386 (memaddr, &info);
 }
index 01bbd926ccf1fa6f59cab0192dd7f72e3ae4700e..321ff5dfa706e481155fd9af368b16777a362c44 100644 (file)
@@ -20,9 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "defs.h"
 #include "dis-asm.h"
 
-/* m68k instructions are never longer than this many bytes.  */
-#define MAXLEN 22
-\f
 /* Print the m68k instruction at address MEMADDR in debugged memory,
    on STREAM.  Returns length of the instruction, in bytes.  */
 
@@ -31,16 +28,9 @@ print_insn (memaddr, stream)
      CORE_ADDR memaddr;
      FILE *stream;
 {
-  unsigned char buffer[MAXLEN];
-  register int i;
-  register unsigned char *p;
-  register char *d;
-  register int bestmask;
-  int best;
   disassemble_info info;
 
   GDB_INIT_DISASSEMBLE_INFO(info, stream);
 
-  read_memory (memaddr, (char *) buffer, MAXLEN);
-  return print_insn_m68k (memaddr, buffer, &info);
+  return print_insn_m68k (memaddr, &info);
 }
index da4232ed5b102b2bbd1a9bf49079d06d527e97da..eec22c519a3556b8996058eac6007359b629db86 100644 (file)
@@ -20,9 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "defs.h"
 #include "dis-asm.h"
 
-/* Mips instructions are never longer than this many bytes.  */
-#define MAXLEN 4
-
 /* Print the mips instruction at address MEMADDR in debugged memory,
    on STREAM.  Returns length of the instruction, in bytes, which
    is always 4.  */
@@ -32,16 +29,13 @@ print_insn (memaddr, stream)
      CORE_ADDR memaddr;
      FILE *stream;
 {
-  unsigned char buffer[MAXLEN];
   disassemble_info info;
 
   GDB_INIT_DISASSEMBLE_INFO(info, stream);
 
-  read_memory (memaddr, buffer, MAXLEN);
-
   /* print_insn_mips is in opcodes/mips-dis.c.  */
   if (TARGET_BYTE_ORDER == BIG_ENDIAN)
-    print_insn_big_mips (memaddr, buffer, &info);
+    print_insn_big_mips (memaddr, &info);
   else
-    print_insn_little_mips (memaddr, buffer, &info);
+    print_insn_little_mips (memaddr, &info);
 }
index ff91a76efe9c4c3eaf65d22dcc5b5b991214c093..10e4e4b31cef1b158fe4c6952d344f82a8189a34 100644 (file)
@@ -208,19 +208,17 @@ print_insn (memaddr, stream)
      CORE_ADDR memaddr;
      FILE *stream;
 {
-  char temp[20];
   disassemble_info info;
 
   GDB_INIT_DISASSEMBLE_INFO(info, stream);
 
-  read_memory (memaddr, temp, 20);
   if (BIG)
     {
-      return print_insn_z8001 (memaddr, temp, &info);
+      return print_insn_z8001 (memaddr, &info);
     }
   else
     {
-      return print_insn_z8002 (memaddr, temp, &info);
+      return print_insn_z8002 (memaddr, &info);
     }
 }
 
index 2b6accd399e8371d5ee17b09cabe072a99c80792..b118400fb6beab86beccb7c86261ba7750fd6d77 100644 (file)
@@ -1,3 +1,14 @@
+Tue Mar 30 19:09:23 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * dis-asm.h (disassembler_info): Add read_memory_func,
+       memory_error_func, buffer, buffer_length, and buffer_vma.
+       ({GDB_,}INIT_DISASSEMBLE_INFO): Set them.
+       print_insn_*: Remove second argument.
+
+Tue Mar 30 14:48:55 1993  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * bfd.h: Update for lma field of section.
+
 Tue Mar 30 12:22:55 1993  Jim Kingdon  (kingdon@cygnus.com)
 
        * ansidecl.h: Use ANSI versions on AIX regardless of __STDC__.
index d229924aa28087ff747465be6a049c2599316316..da13bf7f9b6e3572e7ee0b386026d90960a07b6b 100644 (file)
@@ -7,26 +7,76 @@ typedef int (*fprintf_ftype) PARAMS((FILE*, const char*, ...));
 typedef struct disassemble_info {
   fprintf_ftype fprintf_func;
   FILE *stream;
+
+  /* For use by the disassembler.  */
   int flags;
+  PTR private_data;
+
+  /* Function used to get bytes to disassemble.  MEMADDR is the
+     address of the stuff to be disassembled, MYADDR is the address to
+     put the bytes in, and LENGTH is the number of bytes to read.
+     INFO is a pointer to this struct.
+     Returns an errno value or 0 for success.  */
+  int (*read_memory_func)
+    PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, int length,
+            struct disassemble_info *info));
+
+  /* Function which should be called if we get an error that we can't
+     recover from.  STATUS is the errno value from read_memory_func and
+     MEMADDR is the address that we were trying to read.  INFO is a
+     pointer to this struct.  */
+  void (*memory_error_func)
+    PARAMS ((int status, bfd_vma memaddr, struct disassemble_info *info));
+
+  /* These are for buffer_read_memory.  */
+  bfd_byte *buffer;
+  bfd_vma buffer_vma;
+  int buffer_length;
 } disassemble_info;
 
-typedef int (*disassembler_ftype)
-     PARAMS((bfd_vma, bfd_byte *, disassemble_info *));
+/* Here is a function which callers may wish to use for read_memory_func.
+   It gets bytes from a buffer.  */
+extern int buffer_read_memory
+  PARAMS ((bfd_vma, bfd_byte *, int, struct disassemble_info *));
+
+/* This function goes with buffer_read_memory.
+   It prints a message using info->fprintf_func and info->stream.  */
+extern void perror_memory PARAMS ((int, bfd_vma, struct disassemble_info *));
 
 #define INIT_DISASSEMBLE_INFO(INFO, STREAM) \
-  INFO.fprintf_func = (fprintf_ftype)fprintf, \
-  INFO.stream = (STREAM)
+  (INFO).fprintf_func = (fprintf_ftype)fprintf, \
+  (INFO).stream = (STREAM), \
+  (INFO).buffer = NULL, \
+  (INFO).buffer_vma = 0, \
+  (INFO).buffer_length = 0, \
+  (INFO).read_memory_func = buffer_read_memory, \
+  (INFO).memory_error_func = perror_memory
+
+/* GDB--Like target_read_memory, but slightly different parameters.  */
+extern int
+dis_asm_read_memory PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, int len));
+
+/* GDB--Like memory_error with slightly different parameters.  */
+extern void
+dis_asm_memory_error
+  PARAMS ((int status, bfd_vma memaddr, disassembler_info *info));
 
 #define GDB_INIT_DISASSEMBLE_INFO(INFO, STREAM) \
-  INFO.fprintf_func = (fprintf_ftype)fprintf_filtered, \
-  INFO.stream = (STREAM)
-
-/* Standard dis-assemblers. */
-
-extern int print_insn_big_mips PARAMS ((bfd_vma, bfd_byte*,disassemble_info*));
-extern int print_insn_little_mips
-  PARAMS ((bfd_vma,bfd_byte*,disassemble_info*));
-extern int print_insn_i386 PARAMS ((bfd_vma,bfd_byte*,disassemble_info*));
-extern int print_insn_m68k PARAMS ((bfd_vma,bfd_byte*,disassemble_info*));
-extern int print_insn_z8001 PARAMS ((bfd_vma,bfd_byte*,disassemble_info*));
-extern int print_insn_z8002 PARAMS ((bfd_vma,bfd_byte*,disassemble_info*));
+  (INFO).fprintf_func = (fprintf_ftype)fprintf_filtered, \
+  (INFO).stream = (STREAM), \
+  (INFO).read_memory_func = dis_asm_read_memory, \
+  (INFO).memory_error_func = dis_asm_memory_error
+
+
+/* Standard disassemblers.  Disassemble one instruction at the given
+   target address.  Return number of bytes processed.  */
+typedef int (*disassembler_ftype)
+     PARAMS((bfd_vma, disassemble_info *));
+
+extern int print_insn_big_mips PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_mips PARAMS ((bfd_vma,disassemble_info*));
+extern int print_insn_i386 PARAMS ((bfd_vma,disassemble_info*));
+extern int print_insn_m68k PARAMS ((bfd_vma,disassemble_info*));
+extern int print_insn_z8001 PARAMS ((bfd_vma,disassemble_info*));
+extern int print_insn_z8002 PARAMS ((bfd_vma,disassemble_info*));
+extern int print_insn_h8500 PARAMS ((bfd_vma,disassemble_info*));
index ba4f85200c35dc5093751f78d3f71005d39d57a0..31c03ad7ea82bf3823f6abbc3b53f63b28d211f7 100644 (file)
@@ -1,3 +1,19 @@
+Wed Mar 31 10:07:04 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * dis-buf.c: New file, for new read_memory_func interface.
+       Makefile.in (OFILES): Include it.
+       m68k-dis.c, i386-dis.c, h8500-dis.c, mips-dis.c, z8k-dis.c:
+       Use new read_memory_func interface.
+
+Mon Mar 29 14:02:17 1993  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * h8500-dis.c (print_insn_h8500): Get sign of fp offsets right.
+       * h8500-opc.h: Fix couple of opcodes.
+
+Wed Mar 24 02:03:36 1993  david d `zoo' zuhn  (zoo at poseidon.cygnus.com)
+
+       * Makefile.in: add dvi & installcheck targets
+
 Mon Mar 22 18:55:04 1993  John Gilmore  (gnu@cygnus.com)
 
        * Makefile.in:  Update for h8500-dis.c.
index 517f7531a7ba28fe56e54a62a3dc70c588b5f9c1..47dbd2eb4a56f931d74549f545e250a99aaa5dc4 100644 (file)
@@ -62,7 +62,7 @@ DEP = mkdep
 TARGETLIB = libopcodes.a
 
 
-DIS_LIBS = i386-dis.o z8k-dis.o m68k-dis.o mips-dis.o h8500-dis.o
+DIS_LIBS = i386-dis.o z8k-dis.o m68k-dis.o mips-dis.o h8500-dis.o dis-buf.o
 
 OFILES = $(DIS_LIBS) sparc-opc.o m68881-ext.o
 #### host and target dependent Makefile fragments come in here.
@@ -95,11 +95,12 @@ all: $(TARGETLIB)
 
 .NOEXPORT:
 
-check:
+installcheck check:
 
 info:
 clean-info:
 install-info:
+dvi:
 
 # HDEPFILES comes from the host config; TDEPFILES from the target config.
 
diff --git a/opcodes/h8500-dis.c b/opcodes/h8500-dis.c
new file mode 100644 (file)
index 0000000..856e580
--- /dev/null
@@ -0,0 +1,330 @@
+/* Disassemble h8500 instructions.
+   Copyright (C) 1993 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#define DISASSEMBLER_TABLE
+#define DEFINE_TABLE
+
+#include "h8500-opc.h"
+#include "dis-asm.h"
+
+/* Maximum length of an instruction.  */
+#define MAXLEN 8
+
+#include <setjmp.h>
+
+struct private
+{
+  /* Points to first byte not fetched.  */
+  bfd_byte *max_fetched;
+  bfd_byte the_buffer[MAXLEN];
+  bfd_vma insn_start;
+  jmp_buf bailout;
+};
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
+   on error.  */
+#define FETCH_DATA(info, addr) \
+  ((addr) <= ((struct private *)(info->private_data))->max_fetched \
+   ? 1 : fetch_data ((info), (addr)))
+
+static int
+fetch_data (info, addr)
+     struct disassemble_info *info;
+     bfd_byte *addr;
+{
+  int status;
+  struct private *priv = (struct 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 (status != 0)
+    {
+      (*info->memory_error_func) (status, start, info);
+      longjmp (priv->bailout);
+    }
+  else
+    priv->max_fetched = addr;
+  return 1;
+}
+
+static char *crname[] =
+{"sr", "ccr", "*", "br", "ep", "dp", "*", "tp"};
+
+int
+print_insn_h8500 (addr, info)
+     unsigned long addr;
+     disassemble_info *info;
+{
+  h8500_opcode_info *opcode;
+  void *stream = info->stream;
+  fprintf_ftype func = info->fprintf_func;
+
+  struct private priv;
+  bfd_byte *buffer = priv.the_buffer;
+
+  info->private_data = (PTR) &priv;
+  priv.max_fetched = priv.the_buffer;
+  priv.insn_start = addr;
+  if (setjmp (priv.bailout) != 0)
+    /* Error return.  */
+    return -1;
+
+  /* Run down the table to find the one which matches */
+  for (opcode = h8500_table; opcode->name; opcode++)
+    {
+      int byte;
+      int rn;
+      int rd;
+      int rs;
+      int disp;
+      int abs;
+      int imm;
+      int pcrel;
+      int qim;
+      int i;
+      int cr;
+      for (byte = 0; byte < opcode->length; byte++)
+       {
+         FETCH_DATA (info, buffer + byte + 1);
+         if ((buffer[byte] & opcode->bytes[byte].mask)
+             != (opcode->bytes[byte].contents))
+           {
+             goto next;
+           }
+         else
+           {
+             /* extract any info parts */
+             switch (opcode->bytes[byte].insert)
+               {
+               case 0:
+               case FP:
+                 break;
+               default:
+                 func (stream, "can't cope with insert %d\n",
+                       opcode->bytes[byte].insert);
+                 break;
+               case RN:
+                 rn = buffer[byte] & 0x7;
+                 break;
+               case RS:
+                 rs = buffer[byte] & 0x7;
+                 break;
+               case CRB:
+                 cr = buffer[byte] & 0x7;
+                 if (cr == 0)
+                   goto next;
+                 break;
+               case CRW:
+                 cr = buffer[byte] & 0x7;
+                 if (cr != 0)
+                   goto next;
+                 break;
+               case DISP16:
+                 FETCH_DATA (info, buffer + byte + 2);
+                 disp = (buffer[byte] << 8) | (buffer[byte + 1]);
+                 break;
+               case FPIND_D8:
+               case DISP8:
+                 disp = ((char) (buffer[byte]));
+                 break;
+               case RD:
+               case RDIND:
+                 rd = buffer[byte] & 0x7;
+                 break;
+               case ABS24:
+                 FETCH_DATA (info, buffer + byte + 3);
+                 abs =
+                   (buffer[byte] << 16)
+                   | (buffer[byte + 1] << 8)
+                   | (buffer[byte + 2]);
+                 break;
+               case ABS16:
+                 FETCH_DATA (info, buffer + byte + 2);
+                 abs = (buffer[byte] << 8) | (buffer[byte + 1]);
+                 break;
+               case ABS8:
+                 abs = (buffer[byte]);
+                 break;
+               case IMM16:
+                 FETCH_DATA (info, buffer + byte + 2);
+                 imm = (buffer[byte] << 8) | (buffer[byte + 1]);
+                 break;
+               case IMM4:
+                 imm = (buffer[byte]) & 0xf;
+                 break;
+               case IMM8:
+               case RLIST:
+                 imm = (buffer[byte]);
+                 break;
+               case PCREL16:
+                 FETCH_DATA (info, buffer + byte + 2);
+                 pcrel = (buffer[byte] << 8) | (buffer[byte + 1]);
+                 break;
+               case PCREL8:
+                 pcrel = (buffer[byte]);
+                 break;
+               case QIM:
+                 switch (buffer[byte] & 0x7)
+                   {
+                   case 0:
+                     qim = 1;
+                     break;
+                   case 1:
+                     qim = 2;
+                     break;
+                   case 4:
+                     qim = -1;
+                     break;
+                   case 5:
+                     qim = -2;
+                     break;
+                   }
+                 break;
+
+               }
+           }
+       }
+      /* We get here when all the masks have passed so we can output the
+        operands*/
+      FETCH_DATA (info, buffer + opcode->length);
+      for (i = 0; i < opcode->length; i++)
+       {
+         (func) (stream, "%02x ", buffer[i]);
+       }
+      for (; i < 6; i++)
+       {
+         (func) (stream, "   ");
+       }
+      (func) (stream, "%s\t", opcode->name);
+      for (i = 0; i < opcode->nargs; i++)
+       {
+         if (i)
+           (func) (stream, ",");
+         switch (opcode->arg_type[i])
+           {
+           case FP:
+             func (stream, "fp");
+             break;
+           case RNIND_D16:
+             func (stream, "@(0x%x:16,r%d)", disp, rn);
+             break;
+           case RNIND_D8:
+             func (stream, "@(0x%x:8 (%d),r%d)", disp & 0xff, disp, rn);
+             break;
+           case RDIND_D16:
+             func (stream, "@(0x%x:16,r%d)", disp, rd);
+             break;
+           case RDIND_D8:
+             func (stream, "@(0x%x:8 (%d), r%d)", disp & 0xff, disp, rd);
+             break;
+           case FPIND_D8:
+             func (stream, "@(0x%x:8 (%d), fp)", disp & 0xff, disp, rn);
+             break;
+           case CRB:
+           case CRW:
+             func (stream, "%s", crname[cr]);
+             break;
+           case RN:
+             func (stream, "r%d", rn);
+             break;
+           case RD:
+             func (stream, "r%d", rd);
+             break;
+           case RS:
+             func (stream, "r%d", rs);
+             break;
+           case RNDEC:
+             func (stream, "@-r%d", rn);
+             break;
+           case RNINC:
+             func (stream, "@r%d+", rn);
+             break;
+           case RNIND:
+             func (stream, "@r%d", rn);
+             break;
+           case RDIND:
+             func (stream, "@r%d", rd);
+             break;
+           case SPINC:
+             func (stream, "@sp+");
+             break;
+           case SPDEC:
+             func (stream, "@-sp");
+             break;
+           case ABS24:
+             func (stream, "@0x%0x:24", abs);
+             break;
+           case ABS16:
+             func (stream, "@0x%0x:16", abs & 0xffff);
+             break;
+           case ABS8:
+             func (stream, "@0x%0x:8", abs & 0xff);
+             break;
+           case IMM16:
+             func (stream, "#0x%0x:16", imm & 0xffff);
+             break;
+           case RLIST:
+             {
+               int i;
+               int nc = 0;
+               func (stream, "(");
+               for (i = 0; i < 8; i++)
+                 {
+                   if (imm & (1 << i))
+                     {
+                       if (nc)
+                         func (stream, ",");
+                       nc += 1;
+                     }
+                   func (stream, "r%d", i);
+                 }
+               func (stream, ")");
+             }
+             break;
+           case IMM8:
+             func (stream, "#0x%0x:8", imm & 0xff);
+             break;
+           case PCREL16:
+             func (stream, "0x%0x:16", (pcrel + addr + opcode->length) & 0xffff);
+             break;
+           case PCREL8:
+             func (stream, "#0x%0x:8",
+                   ((char) pcrel + addr + opcode->length) & 0xffff);
+             break;
+           case QIM:
+             func (stream, "#%d:q", qim);
+             break;
+           case IMM4:
+             func (stream, "#%d:4", imm);
+             break;
+           }
+       }
+      return opcode->length;
+    next:;
+    }
+
+  /* Couldn't understand anything */
+  func (stream, "%02x\t\t*unknown*", buffer[0]);
+  return 1;
+
+}
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
new file mode 100644 (file)
index 0000000..6bdfa5f
--- /dev/null
@@ -0,0 +1,1952 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+   Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ *  modified by John Hassey (hassey@dg-rtp.dg.com)
+ */
+
+/*
+ * The main tables describing the instructions is essentially a copy
+ * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ * Programmers Manual.  Usually, there is a capital letter, followed
+ * by a small letter.  The capital letter tell the addressing mode,
+ * and the small letter tells about the operand size.  Refer to 
+ * the Intel manual for details.
+ */
+
+#include "dis-asm.h"
+
+#define MAXLEN 20
+
+#include <setjmp.h>
+
+struct private
+{
+  /* Points to first byte not fetched.  */
+  bfd_byte *max_fetched;
+  bfd_byte the_buffer[MAXLEN];
+  bfd_vma insn_start;
+  jmp_buf bailout;
+};
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
+   on error.  */
+#define FETCH_DATA(info, addr) \
+  ((addr) <= ((struct private *)(info->private_data))->max_fetched \
+   ? 1 : fetch_data ((info), (addr)))
+
+static int
+fetch_data (info, addr)
+     struct disassemble_info *info;
+     bfd_byte *addr;
+{
+  int status;
+  struct private *priv = (struct 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 (status != 0)
+    {
+      (*info->memory_error_func) (status, start, info);
+      longjmp (priv->bailout);
+    }
+  else
+    priv->max_fetched = addr;
+  return 1;
+}
+
+#define Eb OP_E, b_mode
+#define indirEb OP_indirE, b_mode
+#define Gb OP_G, b_mode
+#define Ev OP_E, v_mode
+#define indirEv OP_indirE, v_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_E, 0
+#define Mp OP_E, 0             /* ? */
+#define Gv OP_G, v_mode
+#define Gw OP_G, w_mode
+#define Rw OP_rm, w_mode
+#define Rd OP_rm, d_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode      /* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iw OP_I, w_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define ONE OP_ONE, 0
+#define Cd OP_C, d_mode
+#define Dd OP_D, d_mode
+#define Td OP_T, d_mode
+
+#define eAX OP_REG, eAX_reg
+#define eBX OP_REG, eBX_reg
+#define eCX OP_REG, eCX_reg
+#define eDX OP_REG, eDX_reg
+#define eSP OP_REG, eSP_reg
+#define eBP OP_REG, eBP_reg
+#define eSI OP_REG, eSI_reg
+#define eDI OP_REG, eDI_reg
+#define AL OP_REG, al_reg
+#define CL OP_REG, cl_reg
+#define DL OP_REG, dl_reg
+#define BL OP_REG, bl_reg
+#define AH OP_REG, ah_reg
+#define CH OP_REG, ch_reg
+#define DH OP_REG, dh_reg
+#define BH OP_REG, bh_reg
+#define AX OP_REG, ax_reg
+#define DX OP_REG, dx_reg
+#define indirDX OP_REG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, lptr
+#define Av OP_DIR, v_mode
+#define Ob OP_OFF, b_mode
+#define Ov OP_OFF, v_mode
+#define Xb OP_DSSI, b_mode
+#define Xv OP_DSSI, v_mode
+#define Yb OP_ESDI, b_mode
+#define Yv OP_ESDI, v_mode
+
+#define es OP_REG, es_reg
+#define ss OP_REG, ss_reg
+#define cs OP_REG, cs_reg
+#define ds OP_REG, ds_reg
+#define fs OP_REG, fs_reg
+#define gs OP_REG, gs_reg
+
+int OP_E(), OP_indirE(), OP_G(), OP_I(), OP_sI(), OP_REG();
+int OP_J(), OP_SEG();
+int OP_DIR(), OP_OFF(), OP_DSSI(), OP_ESDI(), OP_ONE(), OP_C();
+int OP_D(), OP_T(), OP_rm();
+
+static void dofloat (), putop (), append_prefix (), set_op ();
+static int get16 (), get32 ();
+
+#define b_mode 1
+#define v_mode 2
+#define w_mode 3
+#define d_mode 4
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+#define eAX_reg 107
+#define eCX_reg 108
+#define eDX_reg 109
+#define eBX_reg 110
+#define eSP_reg 111
+#define eBP_reg 112
+#define eSI_reg 113
+#define eDI_reg 114
+
+#define lptr 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define indir_dx_reg 150
+
+#define GRP1b NULL, NULL, 0
+#define GRP1S NULL, NULL, 1
+#define GRP1Ss NULL, NULL, 2
+#define GRP2b NULL, NULL, 3
+#define GRP2S NULL, NULL, 4
+#define GRP2b_one NULL, NULL, 5
+#define GRP2S_one NULL, NULL, 6
+#define GRP2b_cl NULL, NULL, 7
+#define GRP2S_cl NULL, NULL, 8
+#define GRP3b NULL, NULL, 9
+#define GRP3S NULL, NULL, 10
+#define GRP4  NULL, NULL, 11
+#define GRP5  NULL, NULL, 12
+#define GRP6  NULL, NULL, 13
+#define GRP7 NULL, NULL, 14
+#define GRP8 NULL, NULL, 15
+
+#define FLOATCODE 50
+#define FLOAT NULL, NULL, FLOATCODE
+
+struct dis386 {
+  char *name;
+  int (*op1)();
+  int bytemode1;
+  int (*op2)();
+  int bytemode2;
+  int (*op3)();
+  int bytemode3;
+};
+
+struct dis386 dis386[] = {
+  /* 00 */
+  { "addb",    Eb, Gb },
+  { "addS",    Ev, Gv },
+  { "addb",    Gb, Eb },
+  { "addS",    Gv, Ev },
+  { "addb",    AL, Ib },
+  { "addS",    eAX, Iv },
+  { "pushl",   es },
+  { "popl",    es },
+  /* 08 */
+  { "orb",     Eb, Gb },
+  { "orS",     Ev, Gv },
+  { "orb",     Gb, Eb },
+  { "orS",     Gv, Ev },
+  { "orb",     AL, Ib },
+  { "orS",     eAX, Iv },
+  { "pushl",   cs },
+  { "(bad)" }, /* 0x0f extended opcode escape */
+  /* 10 */
+  { "adcb",    Eb, Gb },
+  { "adcS",    Ev, Gv },
+  { "adcb",    Gb, Eb },
+  { "adcS",    Gv, Ev },
+  { "adcb",    AL, Ib },
+  { "adcS",    eAX, Iv },
+  { "pushl",   ss },
+  { "popl",    ss },
+  /* 18 */
+  { "sbbb",    Eb, Gb },
+  { "sbbS",    Ev, Gv },
+  { "sbbb",    Gb, Eb },
+  { "sbbS",    Gv, Ev },
+  { "sbbb",    AL, Ib },
+  { "sbbS",    eAX, Iv },
+  { "pushl",   ds },
+  { "popl",    ds },
+  /* 20 */
+  { "andb",    Eb, Gb },
+  { "andS",    Ev, Gv },
+  { "andb",    Gb, Eb },
+  { "andS",    Gv, Ev },
+  { "andb",    AL, Ib },
+  { "andS",    eAX, Iv },
+  { "(bad)" },                 /* SEG ES prefix */
+  { "daa" },
+  /* 28 */
+  { "subb",    Eb, Gb },
+  { "subS",    Ev, Gv },
+  { "subb",    Gb, Eb },
+  { "subS",    Gv, Ev },
+  { "subb",    AL, Ib },
+  { "subS",    eAX, Iv },
+  { "(bad)" },                 /* SEG CS prefix */
+  { "das" },
+  /* 30 */
+  { "xorb",    Eb, Gb },
+  { "xorS",    Ev, Gv },
+  { "xorb",    Gb, Eb },
+  { "xorS",    Gv, Ev },
+  { "xorb",    AL, Ib },
+  { "xorS",    eAX, Iv },
+  { "(bad)" },                 /* SEG SS prefix */
+  { "aaa" },
+  /* 38 */
+  { "cmpb",    Eb, Gb },
+  { "cmpS",    Ev, Gv },
+  { "cmpb",    Gb, Eb },
+  { "cmpS",    Gv, Ev },
+  { "cmpb",    AL, Ib },
+  { "cmpS",    eAX, Iv },
+  { "(bad)" },                 /* SEG DS prefix */
+  { "aas" },
+  /* 40 */
+  { "incS",    eAX },
+  { "incS",    eCX },
+  { "incS",    eDX },
+  { "incS",    eBX },
+  { "incS",    eSP },
+  { "incS",    eBP },
+  { "incS",    eSI },
+  { "incS",    eDI },
+  /* 48 */
+  { "decS",    eAX },
+  { "decS",    eCX },
+  { "decS",    eDX },
+  { "decS",    eBX },
+  { "decS",    eSP },
+  { "decS",    eBP },
+  { "decS",    eSI },
+  { "decS",    eDI },
+  /* 50 */
+  { "pushS",   eAX },
+  { "pushS",   eCX },
+  { "pushS",   eDX },
+  { "pushS",   eBX },
+  { "pushS",   eSP },
+  { "pushS",   eBP },
+  { "pushS",   eSI },
+  { "pushS",   eDI },
+  /* 58 */
+  { "popS",    eAX },
+  { "popS",    eCX },
+  { "popS",    eDX },
+  { "popS",    eBX },
+  { "popS",    eSP },
+  { "popS",    eBP },
+  { "popS",    eSI },
+  { "popS",    eDI },
+  /* 60 */
+  { "pusha" },
+  { "popa" },
+  { "boundS",  Gv, Ma },
+  { "arpl",    Ew, Gw },
+  { "(bad)" },                 /* seg fs */
+  { "(bad)" },                 /* seg gs */
+  { "(bad)" },                 /* op size prefix */
+  { "(bad)" },                 /* adr size prefix */
+  /* 68 */
+  { "pushS",   Iv },           /* 386 book wrong */
+  { "imulS",   Gv, Ev, Iv },
+  { "pushl",   sIb },          /* push of byte really pushes 4 bytes */
+  { "imulS",   Gv, Ev, Ib },
+  { "insb",    Yb, indirDX },
+  { "insS",    Yv, indirDX },
+  { "outsb",   indirDX, Xb },
+  { "outsS",   indirDX, Xv },
+  /* 70 */
+  { "jo",              Jb },
+  { "jno",     Jb },
+  { "jb",              Jb },
+  { "jae",     Jb },
+  { "je",              Jb },
+  { "jne",     Jb },
+  { "jbe",     Jb },
+  { "ja",              Jb },
+  /* 78 */
+  { "js",              Jb },
+  { "jns",     Jb },
+  { "jp",              Jb },
+  { "jnp",     Jb },
+  { "jl",              Jb },
+  { "jnl",     Jb },
+  { "jle",     Jb },
+  { "jg",              Jb },
+  /* 80 */
+  { GRP1b },
+  { GRP1S },
+  { "(bad)" },
+  { GRP1Ss },
+  { "testb",   Eb, Gb },
+  { "testS",   Ev, Gv },
+  { "xchgb",   Eb, Gb },
+  { "xchgS",   Ev, Gv },
+  /* 88 */
+  { "movb",    Eb, Gb },
+  { "movS",    Ev, Gv },
+  { "movb",    Gb, Eb },
+  { "movS",    Gv, Ev },
+  { "movw",    Ew, Sw },
+  { "leaS",    Gv, M },
+  { "movw",    Sw, Ew },
+  { "popS",    Ev },
+  /* 90 */
+  { "nop" },
+  { "xchgS",   eCX, eAX },
+  { "xchgS",   eDX, eAX },
+  { "xchgS",   eBX, eAX },
+  { "xchgS",   eSP, eAX },
+  { "xchgS",   eBP, eAX },
+  { "xchgS",   eSI, eAX },
+  { "xchgS",   eDI, eAX },
+  /* 98 */
+  { "cwtl" },
+  { "cltd" },
+  { "lcall",   Ap },
+  { "(bad)" },         /* fwait */
+  { "pushf" },
+  { "popf" },
+  { "sahf" },
+  { "lahf" },
+  /* a0 */
+  { "movb",    AL, Ob },
+  { "movS",    eAX, Ov },
+  { "movb",    Ob, AL },
+  { "movS",    Ov, eAX },
+  { "movsb",   Yb, Xb },
+  { "movsS",   Yv, Xv },
+  { "cmpsb",   Yb, Xb },
+  { "cmpsS",   Yv, Xv },
+  /* a8 */
+  { "testb",   AL, Ib },
+  { "testS",   eAX, Iv },
+  { "stosb",   Yb, AL },
+  { "stosS",   Yv, eAX },
+  { "lodsb",   AL, Xb },
+  { "lodsS",   eAX, Xv },
+  { "scasb",   AL, Xb },
+  { "scasS",   eAX, Xv },
+  /* b0 */
+  { "movb",    AL, Ib },
+  { "movb",    CL, Ib },
+  { "movb",    DL, Ib },
+  { "movb",    BL, Ib },
+  { "movb",    AH, Ib },
+  { "movb",    CH, Ib },
+  { "movb",    DH, Ib },
+  { "movb",    BH, Ib },
+  /* b8 */
+  { "movS",    eAX, Iv },
+  { "movS",    eCX, Iv },
+  { "movS",    eDX, Iv },
+  { "movS",    eBX, Iv },
+  { "movS",    eSP, Iv },
+  { "movS",    eBP, Iv },
+  { "movS",    eSI, Iv },
+  { "movS",    eDI, Iv },
+  /* c0 */
+  { GRP2b },
+  { GRP2S },
+  { "ret",     Iw },
+  { "ret" },
+  { "lesS",    Gv, Mp },
+  { "ldsS",    Gv, Mp },
+  { "movb",    Eb, Ib },
+  { "movS",    Ev, Iv },
+  /* c8 */
+  { "enter",   Iw, Ib },
+  { "leave" },
+  { "lret",    Iw },
+  { "lret" },
+  { "int3" },
+  { "int",     Ib },
+  { "into" },
+  { "iret" },
+  /* d0 */
+  { GRP2b_one },
+  { GRP2S_one },
+  { GRP2b_cl },
+  { GRP2S_cl },
+  { "aam",     Ib },
+  { "aad",     Ib },
+  { "(bad)" },
+  { "xlat" },
+  /* d8 */
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  /* e0 */
+  { "loopne",  Jb },
+  { "loope",   Jb },
+  { "loop",    Jb },
+  { "jCcxz",   Jb },
+  { "inb",     AL, Ib },
+  { "inS",     eAX, Ib },
+  { "outb",    Ib, AL },
+  { "outS",    Ib, eAX },
+  /* e8 */
+  { "call",    Av },
+  { "jmp",     Jv },
+  { "ljmp",    Ap },
+  { "jmp",     Jb },
+  { "inb",     AL, indirDX },
+  { "inS",     eAX, indirDX },
+  { "outb",    indirDX, AL },
+  { "outS",    indirDX, eAX },
+  /* f0 */
+  { "(bad)" },                 /* lock prefix */
+  { "(bad)" },
+  { "(bad)" },                 /* repne */
+  { "(bad)" },                 /* repz */
+  { "hlt" },
+  { "cmc" },
+  { GRP3b },
+  { GRP3S },
+  /* f8 */
+  { "clc" },
+  { "stc" },
+  { "cli" },
+  { "sti" },
+  { "cld" },
+  { "std" },
+  { GRP4 },
+  { GRP5 },
+};
+
+struct dis386 dis386_twobyte[] = {
+  /* 00 */
+  { GRP6 },
+  { GRP7 },
+  { "larS", Gv, Ew },
+  { "lslS", Gv, Ew },  
+  { "(bad)" },
+  { "(bad)" },
+  { "clts" },
+  { "(bad)" },  
+  /* 08 */
+  { "invd" },
+  { "wbinvd" },
+  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 10 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 18 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 20 */
+  /* these are all backward in appendix A of the intel book */
+  { "movl", Rd, Cd },
+  { "movl", Rd, Dd },
+  { "movl", Cd, Rd },
+  { "movl", Dd, Rd },  
+  { "movl", Rd, Td },
+  { "(bad)" },
+  { "movl", Td, Rd },
+  { "(bad)" },  
+  /* 28 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 30 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 38 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 40 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 48 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 50 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 58 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 60 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 68 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 70 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 78 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 80 */
+  { "jo", Jv },
+  { "jno", Jv },
+  { "jb", Jv },
+  { "jae", Jv },  
+  { "je", Jv },
+  { "jne", Jv },
+  { "jbe", Jv },
+  { "ja", Jv },  
+  /* 88 */
+  { "js", Jv },
+  { "jns", Jv },
+  { "jp", Jv },
+  { "jnp", Jv },  
+  { "jl", Jv },
+  { "jge", Jv },
+  { "jle", Jv },
+  { "jg", Jv },  
+  /* 90 */
+  { "seto", Eb },
+  { "setno", Eb },
+  { "setb", Eb },
+  { "setae", Eb },
+  { "sete", Eb },
+  { "setne", Eb },
+  { "setbe", Eb },
+  { "seta", Eb },
+  /* 98 */
+  { "sets", Eb },
+  { "setns", Eb },
+  { "setp", Eb },
+  { "setnp", Eb },
+  { "setl", Eb },
+  { "setge", Eb },
+  { "setle", Eb },
+  { "setg", Eb },  
+  /* a0 */
+  { "pushl", fs },
+  { "popl", fs },
+  { "(bad)" },
+  { "btS", Ev, Gv },  
+  { "shldS", Ev, Gv, Ib },
+  { "shldS", Ev, Gv, CL },
+  { "(bad)" },
+  { "(bad)" },  
+  /* a8 */
+  { "pushl", gs },
+  { "popl", gs },
+  { "(bad)" },
+  { "btsS", Ev, Gv },  
+  { "shrdS", Ev, Gv, Ib },
+  { "shrdS", Ev, Gv, CL },
+  { "(bad)" },
+  { "imulS", Gv, Ev },  
+  /* b0 */
+  { "cmpxchgb", Eb, Gb },
+  { "cmpxchgS", Ev, Gv },
+  { "lssS", Gv, Mp },  /* 386 lists only Mp */
+  { "btrS", Ev, Gv },  
+  { "lfsS", Gv, Mp },  /* 386 lists only Mp */
+  { "lgsS", Gv, Mp },  /* 386 lists only Mp */
+  { "movzbS", Gv, Eb },
+  { "movzwS", Gv, Ew },  
+  /* b8 */
+  { "(bad)" },
+  { "(bad)" },
+  { GRP8 },
+  { "btcS", Ev, Gv },  
+  { "bsfS", Gv, Ev },
+  { "bsrS", Gv, Ev },
+  { "movsbS", Gv, Eb },
+  { "movswS", Gv, Ew },  
+  /* c0 */
+  { "xaddb", Eb, Gb },
+  { "xaddS", Ev, Gv },
+  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* c8 */
+  { "bswap", eAX },
+  { "bswap", eCX },
+  { "bswap", eDX },
+  { "bswap", eBX },
+  { "bswap", eSP },
+  { "bswap", eBP },
+  { "bswap", eSI },
+  { "bswap", eDI },
+  /* d0 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* d8 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* e0 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* e8 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* f0 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* f8 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *codep;
+static disassemble_info *the_info;
+static int mod;
+static int rm;
+static int reg;
+static void oappend ();
+
+static char *names32[]={
+  "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+};
+static char *names16[] = {
+  "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+};
+static char *names8[] = {
+  "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+};
+static char *names_seg[] = {
+  "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+};
+
+struct dis386 grps[][8] = {
+  /* GRP1b */
+  {
+    { "addb",  Eb, Ib },
+    { "orb",   Eb, Ib },
+    { "adcb",  Eb, Ib },
+    { "sbbb",  Eb, Ib },
+    { "andb",  Eb, Ib },
+    { "subb",  Eb, Ib },
+    { "xorb",  Eb, Ib },
+    { "cmpb",  Eb, Ib }
+  },
+  /* GRP1S */
+  {
+    { "addS",  Ev, Iv },
+    { "orS",   Ev, Iv },
+    { "adcS",  Ev, Iv },
+    { "sbbS",  Ev, Iv },
+    { "andS",  Ev, Iv },
+    { "subS",  Ev, Iv },
+    { "xorS",  Ev, Iv },
+    { "cmpS",  Ev, Iv }
+  },
+  /* GRP1Ss */
+  {
+    { "addS",  Ev, sIb },
+    { "orS",   Ev, sIb },
+    { "adcS",  Ev, sIb },
+    { "sbbS",  Ev, sIb },
+    { "andS",  Ev, sIb },
+    { "subS",  Ev, sIb },
+    { "xorS",  Ev, sIb },
+    { "cmpS",  Ev, sIb }
+  },
+  /* GRP2b */
+  {
+    { "rolb",  Eb, Ib },
+    { "rorb",  Eb, Ib },
+    { "rclb",  Eb, Ib },
+    { "rcrb",  Eb, Ib },
+    { "shlb",  Eb, Ib },
+    { "shrb",  Eb, Ib },
+    { "(bad)" },
+    { "sarb",  Eb, Ib },
+  },
+  /* GRP2S */
+  {
+    { "rolS",  Ev, Ib },
+    { "rorS",  Ev, Ib },
+    { "rclS",  Ev, Ib },
+    { "rcrS",  Ev, Ib },
+    { "shlS",  Ev, Ib },
+    { "shrS",  Ev, Ib },
+    { "(bad)" },
+    { "sarS",  Ev, Ib },
+  },
+  /* GRP2b_one */
+  {
+    { "rolb",  Eb },
+    { "rorb",  Eb },
+    { "rclb",  Eb },
+    { "rcrb",  Eb },
+    { "shlb",  Eb },
+    { "shrb",  Eb },
+    { "(bad)" },
+    { "sarb",  Eb },
+  },
+  /* GRP2S_one */
+  {
+    { "rolS",  Ev },
+    { "rorS",  Ev },
+    { "rclS",  Ev },
+    { "rcrS",  Ev },
+    { "shlS",  Ev },
+    { "shrS",  Ev },
+    { "(bad)" },
+    { "sarS",  Ev },
+  },
+  /* GRP2b_cl */
+  {
+    { "rolb",  Eb, CL },
+    { "rorb",  Eb, CL },
+    { "rclb",  Eb, CL },
+    { "rcrb",  Eb, CL },
+    { "shlb",  Eb, CL },
+    { "shrb",  Eb, CL },
+    { "(bad)" },
+    { "sarb",  Eb, CL },
+  },
+  /* GRP2S_cl */
+  {
+    { "rolS",  Ev, CL },
+    { "rorS",  Ev, CL },
+    { "rclS",  Ev, CL },
+    { "rcrS",  Ev, CL },
+    { "shlS",  Ev, CL },
+    { "shrS",  Ev, CL },
+    { "(bad)" },
+    { "sarS",  Ev, CL }
+  },
+  /* GRP3b */
+  {
+    { "testb", Eb, Ib },
+    { "(bad)", Eb },
+    { "notb",  Eb },
+    { "negb",  Eb },
+    { "mulb",  AL, Eb },
+    { "imulb", AL, Eb },
+    { "divb",  AL, Eb },
+    { "idivb", AL, Eb }
+  },
+  /* GRP3S */
+  {
+    { "testS", Ev, Iv },
+    { "(bad)" },
+    { "notS",  Ev },
+    { "negS",  Ev },
+    { "mulS",  eAX, Ev },
+    { "imulS", eAX, Ev },
+    { "divS",  eAX, Ev },
+    { "idivS", eAX, Ev },
+  },
+  /* GRP4 */
+  {
+    { "incb", Eb },
+    { "decb", Eb },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* GRP5 */
+  {
+    { "incS",  Ev },
+    { "decS",  Ev },
+    { "call",  indirEv },
+    { "lcall", indirEv },
+    { "jmp",   indirEv },
+    { "ljmp",  indirEv },
+    { "pushS", Ev },
+    { "(bad)" },
+  },
+  /* GRP6 */
+  {
+    { "sldt",  Ew },
+    { "str",   Ew },
+    { "lldt",  Ew },
+    { "ltr",   Ew },
+    { "verr",  Ew },
+    { "verw",  Ew },
+    { "(bad)" },
+    { "(bad)" }
+  },
+  /* GRP7 */
+  {
+    { "sgdt", Ew },
+    { "sidt", Ew },
+    { "lgdt", Ew },
+    { "lidt", Ew },
+    { "smsw", Ew },
+    { "(bad)" },
+    { "lmsw", Ew },
+    { "invlpg", Ew },
+  },
+  /* GRP8 */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "btS",   Ev, Ib },
+    { "btsS",  Ev, Ib },
+    { "btrS",  Ev, Ib },
+    { "btcS",  Ev, Ib },
+  }
+};
+
+#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_ADR 0x400
+#define PREFIX_FWAIT 0x800
+
+static int prefixes;
+
+static void
+ckprefix ()
+{
+  prefixes = 0;
+  while (1)
+    {
+      FETCH_DATA (the_info, codep + 1);
+      switch (*codep)
+       {
+       case 0xf3:
+         prefixes |= PREFIX_REPZ;
+         break;
+       case 0xf2:
+         prefixes |= PREFIX_REPNZ;
+         break;
+       case 0xf0:
+         prefixes |= PREFIX_LOCK;
+         break;
+       case 0x2e:
+         prefixes |= PREFIX_CS;
+         break;
+       case 0x36:
+         prefixes |= PREFIX_SS;
+         break;
+       case 0x3e:
+         prefixes |= PREFIX_DS;
+         break;
+       case 0x26:
+         prefixes |= PREFIX_ES;
+         break;
+       case 0x64:
+         prefixes |= PREFIX_FS;
+         break;
+       case 0x65:
+         prefixes |= PREFIX_GS;
+         break;
+       case 0x66:
+         prefixes |= PREFIX_DATA;
+         break;
+       case 0x67:
+         prefixes |= PREFIX_ADR;
+         break;
+       case 0x9b:
+         prefixes |= PREFIX_FWAIT;
+         break;
+       default:
+         return;
+       }
+      codep++;
+    }
+}
+
+static int dflag;
+static int aflag;              
+
+static char op1out[100], op2out[100], op3out[100];
+static int op_address[3], op_ad, op_index[3];
+static int start_pc;
+
+\f
+/*
+ *   On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ *   (see topic "Redundant prefixes" in the "Differences from 8086"
+ *   section of the "Virtual 8086 Mode" chapter.)
+ * 'pc' should be the address of this instruction, it will
+ *   be used to print the target address if this is a relative jump or call
+ * The function returns the length of this instruction in bytes.
+ */
+
+int
+print_insn_i386 (pc, info)
+     bfd_vma pc;
+     disassemble_info *info;
+{
+  struct dis386 *dp;
+  int i;
+  int enter_instruction;
+  char *first, *second, *third;
+  int needcomma;
+  
+  struct private priv;
+  bfd_byte *inbuf = priv.the_buffer;
+
+  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;
+  op2out[0] = 0;
+  op3out[0] = 0;
+
+  op_index[0] = op_index[1] = op_index[2] = -1;
+
+  the_info = info;
+  start_pc = pc;
+  start_codep = inbuf;
+  codep = inbuf;
+  
+  ckprefix ();
+
+  FETCH_DATA (info, codep + 1);
+  if (*codep == 0xc8)
+    enter_instruction = 1;
+  else
+    enter_instruction = 0;
+  
+  obufp = obuf;
+  
+  if (prefixes & PREFIX_REPZ)
+    oappend ("repz ");
+  if (prefixes & PREFIX_REPNZ)
+    oappend ("repnz ");
+  if (prefixes & PREFIX_LOCK)
+    oappend ("lock ");
+  
+  if ((prefixes & PREFIX_FWAIT)
+      && ((*codep < 0xd8) || (*codep > 0xdf)))
+    {
+      /* fwait not followed by floating point instruction */
+      (*info->fprintf_func) (info->stream, "fwait");
+      return (1);
+    }
+  
+  /* these would be initialized to 0 if disassembling for 8086 or 286 */
+  dflag = 1;
+  aflag = 1;
+  
+  if (prefixes & PREFIX_DATA)
+    dflag ^= 1;
+  
+  if (prefixes & PREFIX_ADR)
+    {
+      aflag ^= 1;
+      oappend ("addr16 ");
+    }
+  
+  if (*codep == 0x0f)
+    {
+      FETCH_DATA (info, codep + 2);
+      dp = &dis386_twobyte[*++codep];
+    }
+  else
+    dp = &dis386[*codep];
+  codep++;
+  FETCH_DATA (info, codep + 1);
+  mod = (*codep >> 6) & 3;
+  reg = (*codep >> 3) & 7;
+  rm = *codep & 7;
+  
+  if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+    {
+      dofloat ();
+    }
+  else
+    {
+      if (dp->name == NULL)
+       dp = &grps[dp->bytemode1][reg];
+      
+      putop (dp->name);
+      
+      obufp = op1out;
+      op_ad = 2;
+      if (dp->op1)
+       (*dp->op1)(dp->bytemode1);
+      
+      obufp = op2out;
+      op_ad = 1;
+      if (dp->op2)
+       (*dp->op2)(dp->bytemode2);
+      
+      obufp = op3out;
+      op_ad = 0;
+      if (dp->op3)
+       (*dp->op3)(dp->bytemode3);
+    }
+  
+  obufp = obuf + strlen (obuf);
+  for (i = strlen (obuf); i < 6; i++)
+    oappend (" ");
+  oappend (" ");
+  (*info->fprintf_func) (info->stream, "%s", obuf);
+  
+  /* enter instruction is printed with operands in the
+   * same order as the intel book; everything else
+   * is printed in reverse order 
+   */
+  if (enter_instruction)
+    {
+      first = op1out;
+      second = op2out;
+      third = op3out;
+      op_ad = op_index[0];
+      op_index[0] = op_index[2];
+      op_index[2] = op_ad;
+    }
+  else
+    {
+      first = op3out;
+      second = op2out;
+      third = op1out;
+    }
+  needcomma = 0;
+  if (*first)
+    {
+      if (op_index[0] != -1)
+       print_address (op_address[op_index[0]], info->stream);
+      else
+       (*info->fprintf_func) (info->stream, "%s", first);
+      needcomma = 1;
+    }
+  if (*second)
+    {
+      if (needcomma)
+       (*info->fprintf_func) (info->stream, ",");
+      if (op_index[1] != -1)
+       print_address (op_address[op_index[1]], info->stream);
+      else
+       (*info->fprintf_func) (info->stream, "%s", second);
+      needcomma = 1;
+    }
+  if (*third)
+    {
+      if (needcomma)
+       (*info->fprintf_func) (info->stream, ",");
+      if (op_index[2] != -1)
+       print_address (op_address[op_index[2]], info->stream);
+      else
+       (*info->fprintf_func) (info->stream, "%s", third);
+    }
+  return (codep - inbuf);
+}
+
+char *float_mem[] = {
+  /* d8 */
+  "fadds",
+  "fmuls",
+  "fcoms",
+  "fcomps",
+  "fsubs",
+  "fsubrs",
+  "fdivs",
+  "fdivrs",
+  /*  d9 */
+  "flds",
+  "(bad)",
+  "fsts",
+  "fstps",
+  "fldenv",
+  "fldcw",
+  "fNstenv",
+  "fNstcw",
+  /* da */
+  "fiaddl",
+  "fimull",
+  "ficoml",
+  "ficompl",
+  "fisubl",
+  "fisubrl",
+  "fidivl",
+  "fidivrl",
+  /* db */
+  "fildl",
+  "(bad)",
+  "fistl",
+  "fistpl",
+  "(bad)",
+  "fldt",
+  "(bad)",
+  "fstpt",
+  /* dc */
+  "faddl",
+  "fmull",
+  "fcoml",
+  "fcompl",
+  "fsubl",
+  "fsubrl",
+  "fdivl",
+  "fdivrl",
+  /* dd */
+  "fldl",
+  "(bad)",
+  "fstl",
+  "fstpl",
+  "frstor",
+  "(bad)",
+  "fNsave",
+  "fNstsw",
+  /* de */
+  "fiadd",
+  "fimul",
+  "ficom",
+  "ficomp",
+  "fisub",
+  "fisubr",
+  "fidiv",
+  "fidivr",
+  /* df */
+  "fild",
+  "(bad)",
+  "fist",
+  "fistp",
+  "fbld",
+  "fildll",
+  "fbstp",
+  "fistpll",
+};
+
+#define ST OP_ST, 0
+#define STi OP_STi, 0
+int OP_ST(), OP_STi();
+
+#define FGRPd9_2 NULL, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1
+#define FGRPd9_5 NULL, NULL, 2
+#define FGRPd9_6 NULL, NULL, 3
+#define FGRPd9_7 NULL, NULL, 4
+#define FGRPda_5 NULL, NULL, 5
+#define FGRPdb_4 NULL, NULL, 6
+#define FGRPde_3 NULL, NULL, 7
+#define FGRPdf_4 NULL, NULL, 8
+
+struct dis386 float_reg[][8] = {
+  /* d8 */
+  {
+    { "fadd",  ST, STi },
+    { "fmul",  ST, STi },
+    { "fcom",  STi },
+    { "fcomp", STi },
+    { "fsub",  ST, STi },
+    { "fsubr", ST, STi },
+    { "fdiv",  ST, STi },
+    { "fdivr", ST, STi },
+  },
+  /* d9 */
+  {
+    { "fld",   STi },
+    { "fxch",  STi },
+    { FGRPd9_2 },
+    { "(bad)" },
+    { FGRPd9_4 },
+    { FGRPd9_5 },
+    { FGRPd9_6 },
+    { FGRPd9_7 },
+  },
+  /* da */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { FGRPda_5 },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* db */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { FGRPdb_4 },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* dc */
+  {
+    { "fadd",  STi, ST },
+    { "fmul",  STi, ST },
+    { "(bad)" },
+    { "(bad)" },
+    { "fsub",  STi, ST },
+    { "fsubr", STi, ST },
+    { "fdiv",  STi, ST },
+    { "fdivr", STi, ST },
+  },
+  /* dd */
+  {
+    { "ffree", STi },
+    { "(bad)" },
+    { "fst",   STi },
+    { "fstp",  STi },
+    { "fucom", STi },
+    { "fucomp",        STi },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* de */
+  {
+    { "faddp", STi, ST },
+    { "fmulp", STi, ST },
+    { "(bad)" },
+    { FGRPde_3 },
+    { "fsubp", STi, ST },
+    { "fsubrp",        STi, ST },
+    { "fdivp", STi, ST },
+    { "fdivrp",        STi, ST },
+  },
+  /* df */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { FGRPdf_4 },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+  },
+};
+
+
+char *fgrps[][8] = {
+  /* d9_2  0 */
+  {
+    "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* d9_4  1 */
+  {
+    "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+  },
+
+  /* d9_5  2 */
+  {
+    "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+  },
+
+  /* d9_6  3 */
+  {
+    "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+  },
+
+  /* d9_7  4 */
+  {
+    "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+  },
+
+  /* da_5  5 */
+  {
+    "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* db_4  6 */
+  {
+    "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+    "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+  },
+
+  /* de_3  7 */
+  {
+    "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* df_4  8 */
+  {
+    "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+};
+
+static void
+dofloat ()
+{
+  struct dis386 *dp;
+  unsigned char floatop;
+  
+  floatop = codep[-1];
+  
+  if (mod != 3)
+    {
+      putop (float_mem[(floatop - 0xd8) * 8 + reg]);
+      obufp = op1out;
+      OP_E (v_mode);
+      return;
+    }
+  codep++;
+  
+  dp = &float_reg[floatop - 0xd8][reg];
+  if (dp->name == NULL)
+    {
+      putop (fgrps[dp->bytemode1][rm]);
+      /* instruction fnstsw is only one with strange arg */
+      if (floatop == 0xdf
+         && FETCH_DATA (the_info, codep + 1)
+         && *codep == 0xe0)
+       strcpy (op1out, "%eax");
+    }
+  else
+    {
+      putop (dp->name);
+      obufp = op1out;
+      if (dp->op1)
+       (*dp->op1)(dp->bytemode1);
+      obufp = op2out;
+      if (dp->op2)
+       (*dp->op2)(dp->bytemode2);
+    }
+}
+
+/* ARGSUSED */
+int
+OP_ST (ignore)
+     int ignore;
+{
+  oappend ("%st");
+  return (0);
+}
+
+/* ARGSUSED */
+int
+OP_STi (ignore)
+     int ignore;
+{
+  sprintf (scratchbuf, "%%st(%d)", rm);
+  oappend (scratchbuf);
+  return (0);
+}
+
+
+/* capital letters in template are macros */
+static void
+putop (template)
+     char *template;
+{
+  char *p;
+  
+  for (p = template; *p; p++)
+    {
+      switch (*p)
+       {
+       default:
+         *obufp++ = *p;
+         break;
+       case 'C':               /* For jcxz/jecxz */
+         if (aflag == 0)
+           *obufp++ = 'e';
+         break;
+       case 'N':
+         if ((prefixes & PREFIX_FWAIT) == 0)
+           *obufp++ = 'n';
+         break;
+       case 'S':
+         /* operand size flag */
+         if (dflag)
+           *obufp++ = 'l';
+         else
+           *obufp++ = 'w';
+         break;
+       }
+    }
+  *obufp = 0;
+}
+
+static void
+oappend (s)
+     char *s;
+{
+  strcpy (obufp, s);
+  obufp += strlen (s);
+  *obufp = 0;
+}
+
+static void
+append_prefix ()
+{
+  if (prefixes & PREFIX_CS)
+    oappend ("%cs:");
+  if (prefixes & PREFIX_DS)
+    oappend ("%ds:");
+  if (prefixes & PREFIX_SS)
+    oappend ("%ss:");
+  if (prefixes & PREFIX_ES)
+    oappend ("%es:");
+  if (prefixes & PREFIX_FS)
+    oappend ("%fs:");
+  if (prefixes & PREFIX_GS)
+    oappend ("%gs:");
+}
+
+int
+OP_indirE (bytemode)
+     int bytemode;
+{
+  oappend ("*");
+  OP_E (bytemode);
+  return (0);
+}
+
+int
+OP_E (bytemode)
+     int bytemode;
+{
+  int disp;
+  int havesib;
+  int base;
+  int index;
+  int scale;
+  int havebase;
+  
+  /* skip mod/rm byte */
+  codep++;
+  
+  havesib = 0;
+  havebase = 0;
+  disp = 0;
+  
+  if (mod == 3)
+    {
+      switch (bytemode)
+       {
+       case b_mode:
+         oappend (names8[rm]);
+         break;
+       case w_mode:
+         oappend (names16[rm]);
+         break;
+       case v_mode:
+         if (dflag)
+           oappend (names32[rm]);
+         else
+           oappend (names16[rm]);
+         break;
+       default:
+         oappend ("<bad dis table>");
+         break;
+       }
+      return (0);
+    }
+  
+  append_prefix ();
+  if (rm == 4)
+    {
+      havesib = 1;
+      havebase = 1;
+      FETCH_DATA (the_info, codep + 1);
+      scale = (*codep >> 6) & 3;
+      index = (*codep >> 3) & 7;
+      base = *codep & 7;
+      codep++;
+    }
+  
+  switch (mod)
+    {
+    case 0:
+      switch (rm)
+       {
+       case 4:
+         /* implies havesib and havebase */
+         if (base == 5) {
+           havebase = 0;
+           disp = get32 ();
+         }
+         break;
+       case 5:
+         disp = get32 ();
+         break;
+       default:
+         havebase = 1;
+         base = rm;
+         break;
+       }
+      break;
+    case 1:
+      FETCH_DATA (the_info, codep + 1);
+      disp = *(char *)codep++;
+      if (rm != 4)
+       {
+         havebase = 1;
+         base = rm;
+       }
+      break;
+    case 2:
+      disp = get32 ();
+      if (rm != 4)
+       {
+         havebase = 1;
+         base = rm;
+       }
+      break;
+    }
+  
+  if (mod != 0 || rm == 5 || (havesib && base == 5))
+    {
+      sprintf (scratchbuf, "0x%x", disp);
+      oappend (scratchbuf);
+    }
+  
+  if (havebase || havesib) 
+    {
+      oappend ("(");
+      if (havebase)
+       oappend (names32[base]);
+      if (havesib) 
+       {
+         if (index != 4) 
+           {
+             sprintf (scratchbuf, ",%s", names32[index]);
+             oappend (scratchbuf);
+           }
+         sprintf (scratchbuf, ",%d", 1 << scale);
+         oappend (scratchbuf);
+       }
+      oappend (")");
+    }
+  return (0);
+}
+
+int
+OP_G (bytemode)
+     int bytemode;
+{
+  switch (bytemode) 
+    {
+    case b_mode:
+      oappend (names8[reg]);
+      break;
+    case w_mode:
+      oappend (names16[reg]);
+      break;
+    case d_mode:
+      oappend (names32[reg]);
+      break;
+    case v_mode:
+      if (dflag)
+       oappend (names32[reg]);
+      else
+       oappend (names16[reg]);
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      break;
+    }
+  return (0);
+}
+
+static int
+get32 ()
+{
+  int x = 0;
+
+  FETCH_DATA (the_info, codep + 4);
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  x |= (*codep++ & 0xff) << 16;
+  x |= (*codep++ & 0xff) << 24;
+  return (x);
+}
+
+static int
+get16 ()
+{
+  int x = 0;
+
+  FETCH_DATA (the_info, codep + 2);
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  return (x);
+}
+
+static void
+set_op (op)
+     int op;
+{
+  op_index[op_ad] = op_ad;
+  op_address[op_ad] = op;
+}
+
+int
+OP_REG (code)
+     int code;
+{
+  char *s;
+  
+  switch (code) 
+    {
+    case indir_dx_reg: 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];
+               break;
+       case es_reg: case ss_reg: case cs_reg:
+       case ds_reg: case fs_reg: case gs_reg:
+               s = names_seg[code - es_reg];
+               break;
+       case al_reg: case ah_reg: case cl_reg: case ch_reg:
+       case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+               s = names8[code - al_reg];
+               break;
+       case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+       case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+      if (dflag)
+       s = names32[code - eAX_reg];
+      else
+       s = names16[code - eAX_reg];
+      break;
+    default:
+      s = "<internal disassembler error>";
+      break;
+    }
+  oappend (s);
+  return (0);
+}
+
+int
+OP_I (bytemode)
+     int bytemode;
+{
+  int op;
+  
+  switch (bytemode) 
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++ & 0xff;
+      break;
+    case v_mode:
+      if (dflag)
+       op = get32 ();
+      else
+       op = get16 ();
+      break;
+    case w_mode:
+      op = get16 ();
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      return (0);
+    }
+  sprintf (scratchbuf, "$0x%x", op);
+  oappend (scratchbuf);
+  return (0);
+}
+
+int
+OP_sI (bytemode)
+     int bytemode;
+{
+  int op;
+  
+  switch (bytemode) 
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *(char *)codep++;
+      break;
+    case v_mode:
+      if (dflag)
+       op = get32 ();
+      else
+       op = (short)get16();
+      break;
+    case w_mode:
+      op = (short)get16 ();
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      return (0);
+    }
+  sprintf (scratchbuf, "$0x%x", op);
+  oappend (scratchbuf);
+  return (0);
+}
+
+int
+OP_J (bytemode)
+     int bytemode;
+{
+  int disp;
+  int mask = -1;
+  
+  switch (bytemode) 
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      disp = *(char *)codep++;
+      break;
+    case v_mode:
+      if (dflag)
+       disp = get32 ();
+      else
+       {
+         disp = (short)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!  */
+         mask = 0xffff;
+       }
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      return (0);
+    }
+  disp = (start_pc + codep - start_codep + disp) & mask;
+  set_op (disp);
+  sprintf (scratchbuf, "0x%x", disp);
+  oappend (scratchbuf);
+  return (0);
+}
+
+/* ARGSUSED */
+int
+OP_SEG (dummy)
+     int dummy;
+{
+  static char *sreg[] = {
+    "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+  };
+
+  oappend (sreg[reg]);
+  return (0);
+}
+
+int
+OP_DIR (size)
+     int size;
+{
+  int seg, offset;
+  
+  switch (size) 
+    {
+    case lptr:
+      if (aflag) 
+       {
+         offset = get32 ();
+         seg = get16 ();
+       } 
+      else 
+       {
+         offset = get16 ();
+         seg = get16 ();
+       }
+      sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+      oappend (scratchbuf);
+      break;
+    case v_mode:
+      if (aflag)
+       offset = get32 ();
+      else
+       offset = (short)get16 ();
+      
+      offset = start_pc + codep - start_codep + offset;
+      set_op (offset);
+      sprintf (scratchbuf, "0x%x", offset);
+      oappend (scratchbuf);
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      break;
+    }
+  return (0);
+}
+
+/* ARGSUSED */
+int
+OP_OFF (bytemode)
+     int bytemode;
+{
+  int off;
+  
+  if (aflag)
+    off = get32 ();
+  else
+    off = get16 ();
+  
+  sprintf (scratchbuf, "0x%x", off);
+  oappend (scratchbuf);
+  return (0);
+}
+
+/* ARGSUSED */
+int
+OP_ESDI (dummy)
+    int dummy;
+{
+  oappend ("%es:(");
+  oappend (aflag ? "%edi" : "%di");
+  oappend (")");
+  return (0);
+}
+
+/* ARGSUSED */
+int
+OP_DSSI (dummy)
+    int dummy;
+{
+  oappend ("%ds:(");
+  oappend (aflag ? "%esi" : "%si");
+  oappend (")");
+  return (0);
+}
+
+/* ARGSUSED */
+int
+OP_ONE (dummy)
+    int dummy;
+{
+  oappend ("1");
+  return (0);
+}
+
+/* ARGSUSED */
+int
+OP_C (dummy)
+    int dummy;
+{
+  codep++; /* skip mod/rm */
+  sprintf (scratchbuf, "%%cr%d", reg);
+  oappend (scratchbuf);
+  return (0);
+}
+
+/* ARGSUSED */
+int
+OP_D (dummy)
+    int dummy;
+{
+  codep++; /* skip mod/rm */
+  sprintf (scratchbuf, "%%db%d", reg);
+  oappend (scratchbuf);
+  return (0);
+}
+
+/* ARGSUSED */
+int
+OP_T (dummy)
+     int dummy;
+{
+  codep++; /* skip mod/rm */
+  sprintf (scratchbuf, "%%tr%d", reg);
+  oappend (scratchbuf);
+  return (0);
+}
+
+int
+OP_rm (bytemode)
+     int bytemode;
+{
+  switch (bytemode) 
+    {
+    case d_mode:
+      oappend (names32[rm]);
+      break;
+    case w_mode:
+      oappend (names16[rm]);
+      break;
+    }
+  return (0);
+}
diff --git a/opcodes/m68k-dis.c b/opcodes/m68k-dis.c
new file mode 100644 (file)
index 0000000..743ddac
--- /dev/null
@@ -0,0 +1,970 @@
+/* Print Motorola 68k instructions.
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "dis-asm.h"
+#include "ieee-float.h"
+
+extern CONST struct ext_format ext_format_68881;
+
+/* Opcode/m68k.h is a massive table.  As a kludge, break it up into
+   two pieces.  This makes nonportable C -- FIXME -- it assumes that
+   two data items declared near each other will be contiguous in
+   memory.  This kludge can be removed, FIXME, when GCC is fixed to not
+   be a hog about initializers.  */
+
+#ifdef __GNUC__
+#define        BREAK_UP_BIG_DECL       }; \
+                               struct m68k_opcode m68k_opcodes_2[] = {
+#define        AND_OTHER_PART          sizeof (m68k_opcodes_2)
+#endif
+
+#include "opcode/m68k.h"
+
+
+/* Local function prototypes */
+
+static int
+fetch_arg PARAMS ((unsigned char *, int, int));
+
+static void
+print_base PARAMS ((int, int, disassemble_info*));
+
+static unsigned char *
+print_indexed PARAMS ((int, unsigned char *, bfd_vma, disassemble_info *));
+
+static unsigned char *
+print_insn_arg PARAMS ((char *, unsigned char *, unsigned char *, bfd_vma,
+                       disassemble_info *));
+
+/* Sign-extend an (unsigned char). */
+#if __STDC__ == 1
+#define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
+#else
+#define COERCE_SIGNED_CHAR(ch) ((int)(((ch) ^ 0x80) & 0xFF) - 128)
+#endif
+
+CONST char * CONST fpcr_names[] = {
+  "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
+  "fpiar/fpcr", "fpsr/fpcr", "fpiar/fpsr/fpcr"};
+
+static char *reg_names[] = {
+  "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0",
+  "a1", "a2", "a3", "a4", "a5", "fp", "sp", "ps", "pc"};
+
+/* Define accessors for 68K's 1, 2, and 4-byte signed quantities.
+   The _SHIFT values move the quantity to the high order end of an
+   `int' value, so it will sign-extend.  Probably a few more casts
+   are needed to make it compile without warnings on finicky systems.  */
+#define        BITS_PER_BYTE   8
+#define        WORD_SHIFT (BITS_PER_BYTE * ((sizeof (int)) - 2))
+#define        LONG_SHIFT (BITS_PER_BYTE * ((sizeof (int)) - 4))
+
+#define NEXTBYTE(p)  (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1]))
+
+#define NEXTWORD(p)  \
+  (p += 2, FETCH_DATA (info, p), \
+   (((int)((p[-2] << 8) + p[-1])) << WORD_SHIFT) >> WORD_SHIFT)
+
+#define NEXTLONG(p)  \
+  (p += 4, FETCH_DATA (info, p), \
+   (((int)((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])) \
+                                  << LONG_SHIFT) >> LONG_SHIFT)
+
+/* NEXTSINGLE and NEXTDOUBLE handle alignment problems, but not
+ * byte-swapping or other float format differences.  FIXME! */
+
+union number {
+    double d;
+    float f;
+    char c[10];
+};
+
+#define NEXTSINGLE(val, p) \
+  { int i; union number u;\
+    FETCH_DATA (info, p + sizeof (float));\
+    for (i = 0; i < sizeof(float); i++) u.c[i] = *p++; \
+    val = u.f; }
+
+#define NEXTDOUBLE(val, p) \
+  { int i; union number u;\
+    FETCH_DATA (info, p + sizeof (double));\
+    for (i = 0; i < sizeof(double); i++) u.c[i] = *p++; \
+    val = u.d; }
+
+/* Need a function to convert from extended to double precision... */
+#define NEXTEXTEND(p) \
+  (p += 12, FETCH_DATA (info, p), 0.0)
+
+/* Need a function to convert from packed to double
+   precision.   Actually, it's easier to print a
+   packed number than a double anyway, so maybe
+   there should be a special case to handle this... */
+#define NEXTPACKED(p) \
+  (p += 12, FETCH_DATA (info, p), 0.0)
+
+\f
+/* Maximum length of an instruction.  */
+#define MAXLEN 22
+
+#include <setjmp.h>
+
+struct private
+{
+  /* Points to first byte not fetched.  */
+  bfd_byte *max_fetched;
+  bfd_byte the_buffer[MAXLEN];
+  bfd_vma insn_start;
+  jmp_buf bailout;
+};
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
+   on error.  */
+#define FETCH_DATA(info, addr) \
+  ((addr) <= ((struct private *)(info->private_data))->max_fetched \
+   ? 1 : fetch_data ((info), (addr)))
+
+static int
+fetch_data (info, addr)
+     struct disassemble_info *info;
+     bfd_byte *addr;
+{
+  int status;
+  struct private *priv = (struct 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 (status != 0)
+    {
+      (*info->memory_error_func) (status, start, info);
+      longjmp (priv->bailout);
+    }
+  else
+    priv->max_fetched = addr;
+  return 1;
+}
+\f
+static void
+m68k_opcode_error(info, code, place)
+     struct disassemble_info *info;
+     int code, place;
+{
+  (*info->fprintf_func)(info->stream,
+                       "<internal error in opcode table: \"%c%c\">",
+                       code, place);
+}
+
+/* Print the m68k instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn_m68k (memaddr, info)
+     bfd_vma memaddr;
+     disassemble_info *info;
+{
+  register int i;
+  register unsigned char *p;
+  register char *d;
+  register unsigned long bestmask;
+  int best;
+  struct private priv;
+  bfd_byte *buffer = priv.the_buffer;
+
+  info->private_data = (PTR) &priv;
+  priv.max_fetched = priv.the_buffer;
+  priv.insn_start = memaddr;
+  if (setjmp (priv.bailout) != 0)
+    /* Error return.  */
+    return -1;
+
+  bestmask = 0;
+  best = -1;
+  FETCH_DATA (info, buffer + 2);
+  for (i = 0; i < numopcodes; i++)
+    {
+      register unsigned long opcode = m68k_opcodes[i].opcode;
+      register unsigned long match = m68k_opcodes[i].match;
+      if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
+         && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
+         /* Only fetch the next two bytes if we need to.  */
+         && (((0xffff & match) == 0)
+             ||
+             (FETCH_DATA (info, buffer + 4)
+              && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
+              && ((0xff & buffer[3] & match) == (0xff & opcode)))
+             ))
+       {
+         /* Don't use for printout the variants of divul and divsl
+            that have the same register number in two places.
+            The more general variants will match instead.  */
+         for (d = m68k_opcodes[i].args; *d; d += 2)
+           if (d[1] == 'D')
+             break;
+
+         /* Don't use for printout the variants of most floating
+            point coprocessor instructions which use the same
+            register number in two places, as above. */
+         if (*d == 0)
+           for (d = m68k_opcodes[i].args; *d; d += 2)
+             if (d[1] == 't')
+               break;
+
+         if (*d == 0 && match > bestmask)
+           {
+             best = i;
+             bestmask = match;
+           }
+       }
+    }
+
+  /* Handle undefined instructions.  */
+  if (best < 0)
+    {
+      (*info->fprintf_func) (info->stream, "0%o",
+                            (buffer[0] << 8) + buffer[1]);
+      return 2;
+    }
+
+  (*info->fprintf_func) (info->stream, "%s", m68k_opcodes[best].name);
+
+  /* Point at first word of argument data,
+     and at descriptor for first argument.  */
+  p = buffer + 2;
+  
+  /* Why do this this way? -MelloN */
+  for (d = m68k_opcodes[best].args; *d; d += 2)
+    {
+      if (d[0] == '#')
+       {
+         if (d[1] == 'l' && p - buffer < 6)
+           p = buffer + 6;
+         else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
+           p = buffer + 4;
+       }
+      if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
+       p = buffer + 4;
+      if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
+       p = buffer + 6;
+      if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
+       p = buffer + 4;
+    }
+  
+  FETCH_DATA (info, p);
+  
+  d = m68k_opcodes[best].args;
+
+  if (*d)
+    (*info->fprintf_func) (info->stream, " ");
+
+  while (*d)
+    {
+      p = print_insn_arg (d, buffer, p, memaddr + p - buffer, info);
+      d += 2;
+      if (*d && *(d - 2) != 'I' && *d != 'k')
+       (*info->fprintf_func) (info->stream, ",");
+    }
+  return p - buffer;
+}
+
+static unsigned char *
+print_insn_arg (d, buffer, p, addr, info)
+     char *d;
+     unsigned char *buffer;
+     register unsigned char *p;
+     bfd_vma addr;             /* PC for this arg to be relative to */
+     disassemble_info *info;
+{
+  register int val = 0;
+  register int place = d[1];
+  int regno;
+  register CONST char *regname;
+  register unsigned char *p1;
+  double flval;
+  int flt_p;
+
+  switch (*d)
+    {
+    case 'c':          /* cache identifier */
+      {
+        static char *cacheFieldName[] = { "NOP", "dc", "ic", "bc" };
+        val = fetch_arg (buffer, place, 2, info);
+        (*info->fprintf_func) (info->stream, cacheFieldName[val]);
+        break;
+      }
+
+    case 'a':          /* address register indirect only. Cf. case '+'. */
+      {
+        (*info->fprintf_func)
+         (info->stream,
+          "%s@",
+          reg_names [fetch_arg (buffer, place, 3, info) + 8]);
+        break;
+      }
+
+    case '_':          /* 32-bit absolute address for move16. */
+      {
+        val = NEXTLONG (p);
+        (*info->fprintf_func) (info->stream, "@#");
+       print_address (val, info->stream);
+        break;
+      }
+
+    case 'C':
+      (*info->fprintf_func) (info->stream, "ccr");
+      break;
+
+    case 'S':
+      (*info->fprintf_func) (info->stream, "sr");
+      break;
+
+    case 'U':
+      (*info->fprintf_func) (info->stream, "usp");
+      break;
+
+    case 'J':
+      {
+       static struct { char *name; int value; } names[]
+         = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
+            {"tc",  0x003}, {"itt0",0x004}, {"itt1", 0x005},
+             {"dtt0",0x006}, {"dtt1",0x007},
+            {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
+            {"msp", 0x803}, {"isp", 0x804}, {"mmusr",0x805},
+             {"urp", 0x806}, {"srp", 0x807}};
+
+       val = fetch_arg (buffer, place, 12, info);
+       for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
+         if (names[regno].value == val)
+           {
+             (*info->fprintf_func) (info->stream, names[regno].name);
+             break;
+           }
+       if (regno < 0)
+         (*info->fprintf_func) (info->stream, "%d", val);
+      }
+      break;
+
+    case 'Q':
+      val = fetch_arg (buffer, place, 3, info);
+      /* 0 means 8, except for the bkpt instruction... */
+      if (val == 0 && d[1] != 's')
+       val = 8;
+      (*info->fprintf_func) (info->stream, "#%d", val);
+      break;
+
+    case 'M':
+      val = fetch_arg (buffer, place, 8, info);
+      if (val & 0x80)
+       val = val - 0x100;
+      (*info->fprintf_func) (info->stream, "#%d", val);
+      break;
+
+    case 'T':
+      val = fetch_arg (buffer, place, 4, info);
+      (*info->fprintf_func) (info->stream, "#%d", val);
+      break;
+
+    case 'D':
+      (*info->fprintf_func) (info->stream, "%s",
+                            reg_names[fetch_arg (buffer, place, 3, info)]);
+      break;
+
+    case 'A':
+      (*info->fprintf_func)
+       (info->stream, "%s",
+        reg_names[fetch_arg (buffer, place, 3, info) + 010]);
+      break;
+
+    case 'R':
+      (*info->fprintf_func)
+       (info->stream, "%s",
+        reg_names[fetch_arg (buffer, place, 4, info)]);
+      break;
+
+    case 'r':
+      (*info->fprintf_func)
+       (info->stream, "%s@",
+        reg_names[fetch_arg (buffer, place, 4, info)]);
+      break;
+
+    case 'F':
+      (*info->fprintf_func)
+       (info->stream, "fp%d",
+        fetch_arg (buffer, place, 3, info));
+      break;
+
+    case 'O':
+      val = fetch_arg (buffer, place, 6, info);
+      if (val & 0x20)
+       (*info->fprintf_func) (info->stream, "%s", reg_names [val & 7]);
+      else
+       (*info->fprintf_func) (info->stream, "%d", val);
+      break;
+
+    case '+':
+      (*info->fprintf_func)
+       (info->stream, "%s@+",
+        reg_names[fetch_arg (buffer, place, 3, info) + 8]);
+      break;
+
+    case '-':
+      (*info->fprintf_func)
+       (info->stream, "%s@-",
+        reg_names[fetch_arg (buffer, place, 3, info) + 8]);
+      break;
+
+    case 'k':
+      if (place == 'k')
+       (*info->fprintf_func)
+         (info->stream, "{%s}",
+          reg_names[fetch_arg (buffer, place, 3, info)]);
+      else if (place == 'C')
+       {
+         val = fetch_arg (buffer, place, 7, info);
+         if ( val > 63 )               /* This is a signed constant. */
+           val -= 128;
+         (*info->fprintf_func) (info->stream, "{#%d}", val);
+       }
+      else
+       m68k_opcode_error (info, *d, place);
+      break;
+
+    case '#':
+    case '^':
+      p1 = buffer + (*d == '#' ? 2 : 4);
+      if (place == 's')
+       val = fetch_arg (buffer, place, 4, info);
+      else if (place == 'C')
+       val = fetch_arg (buffer, place, 7, info);
+      else if (place == '8')
+       val = fetch_arg (buffer, place, 3, info);
+      else if (place == '3')
+       val = fetch_arg (buffer, place, 8, info);
+      else if (place == 'b')
+       val = NEXTBYTE (p1);
+      else if (place == 'w')
+       val = NEXTWORD (p1);
+      else if (place == 'l')
+       val = NEXTLONG (p1);
+      else
+       m68k_opcode_error (info, *d, place);
+      (*info->fprintf_func) (info->stream, "#%d", val);
+      break;
+
+    case 'B':
+      if (place == 'b')
+       val = NEXTBYTE (p);
+      else if (place == 'B')
+       val = COERCE_SIGNED_CHAR(buffer[1]);
+      else if (place == 'w' || place == 'W')
+       val = NEXTWORD (p);
+      else if (place == 'l' || place == 'L')
+       val = NEXTLONG (p);
+      else if (place == 'g')
+       {
+         val = NEXTBYTE (buffer);
+         if (val == 0)
+           val = NEXTWORD (p);
+         else if (val == -1)
+           val = NEXTLONG (p);
+       }
+      else if (place == 'c')
+       {
+         if (buffer[1] & 0x40)         /* If bit six is one, long offset */
+           val = NEXTLONG (p);
+         else
+           val = NEXTWORD (p);
+       }
+      else
+       m68k_opcode_error (info, *d, place);
+
+      print_address (addr + val, info->stream);
+      break;
+
+    case 'd':
+      val = NEXTWORD (p);
+      (*info->fprintf_func)
+       (info->stream, "%s@(%d)",
+        reg_names[fetch_arg (buffer, place, 3, info)], val);
+      break;
+
+    case 's':
+      (*info->fprintf_func) (info->stream, "%s",
+                            fpcr_names[fetch_arg (buffer, place, 3, info)]);
+      break;
+
+    case 'I':
+      /* Get coprocessor ID... */
+      val = fetch_arg (buffer, 'd', 3, info);
+      
+      if (val != 1)                            /* Unusual coprocessor ID? */
+       (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
+      if (place == 'i')
+       p += 2;                      /* Skip coprocessor extended operands */
+      break;
+
+    case '*':
+    case '~':
+    case '%':
+    case ';':
+    case '@':
+    case '!':
+    case '$':
+    case '?':
+    case '/':
+    case '&':
+    case '`':
+
+      if (place == 'd')
+       {
+         val = fetch_arg (buffer, 'x', 6, info);
+         val = ((val & 7) << 3) + ((val >> 3) & 7);
+       }
+      else
+       val = fetch_arg (buffer, 's', 6, info);
+
+      /* Get register number assuming address register.  */
+      regno = (val & 7) + 8;
+      regname = reg_names[regno];
+      switch (val >> 3)
+       {
+       case 0:
+         (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
+         break;
+
+       case 1:
+         (*info->fprintf_func) (info->stream, "%s", regname);
+         break;
+
+       case 2:
+         (*info->fprintf_func) (info->stream, "%s@", regname);
+         break;
+
+       case 3:
+         (*info->fprintf_func) (info->stream, "%s@+", regname);
+         break;
+
+       case 4:
+         (*info->fprintf_func) (info->stream, "%s@-", regname);
+         break;
+
+       case 5:
+         val = NEXTWORD (p);
+         (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
+         break;
+
+       case 6:
+         p = print_indexed (regno, p, addr, info);
+         break;
+
+       case 7:
+         switch (val & 7)
+           {
+           case 0:
+             val = NEXTWORD (p);
+             (*info->fprintf_func) (info->stream, "@#");
+             print_address (val, info->stream);
+             break;
+
+           case 1:
+             val = NEXTLONG (p);
+             (*info->fprintf_func) (info->stream, "@#");
+             print_address (val, info->stream);
+             break;
+
+           case 2:
+             val = NEXTWORD (p);
+             print_address (addr + val, info->stream);
+             break;
+
+           case 3:
+             p = print_indexed (-1, p, addr, info);
+             break;
+
+           case 4:
+             flt_p = 1;        /* Assume it's a float... */
+             switch( place )
+             {
+               case 'b':
+                 val = NEXTBYTE (p);
+                 flt_p = 0;
+                 break;
+
+               case 'w':
+                 val = NEXTWORD (p);
+                 flt_p = 0;
+                 break;
+
+               case 'l':
+                 val = NEXTLONG (p);
+                 flt_p = 0;
+                 break;
+
+               case 'f':
+                 NEXTSINGLE(flval, p);
+                 break;
+
+               case 'F':
+                 NEXTDOUBLE(flval, p);
+                 break;
+
+               case 'x':
+                 ieee_extended_to_double (&ext_format_68881,
+                                          (char *)p, &flval);
+                 p += 12;
+                 break;
+
+               case 'p':
+                 flval = NEXTPACKED(p);
+                 break;
+
+               default:
+                 m68k_opcode_error (info, *d, place);
+             }
+             if ( flt_p )      /* Print a float? */
+               (*info->fprintf_func) (info->stream, "#%g", flval);
+             else
+               (*info->fprintf_func) (info->stream, "#%d", val);
+             break;
+
+           default:
+             (*info->fprintf_func) (info->stream,
+                                    "<invalid address mode 0%o>",
+                                    (unsigned) val);
+           }
+       }
+      break;
+
+    case 'L':
+    case 'l':
+       if (place == 'w')
+         {
+           char doneany;
+           p1 = buffer + 2;
+           val = NEXTWORD (p1);
+           /* Move the pointer ahead if this point is farther ahead
+              than the last.  */
+           p = p1 > p ? p1 : p;
+           if (val == 0)
+             {
+               (*info->fprintf_func) (info->stream, "#0");
+               break;
+             }
+           if (*d == 'l')
+             {
+               register int newval = 0;
+               for (regno = 0; regno < 16; ++regno)
+                 if (val & (0x8000 >> regno))
+                   newval |= 1 << regno;
+               val = newval;
+             }
+           val &= 0xffff;
+           doneany = 0;
+           for (regno = 0; regno < 16; ++regno)
+             if (val & (1 << regno))
+               {
+                 int first_regno;
+                 if (doneany)
+                   (*info->fprintf_func) (info->stream, "/");
+                 doneany = 1;
+                 (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
+                 first_regno = regno;
+                 while (val & (1 << (regno + 1)))
+                   ++regno;
+                 if (regno > first_regno)
+                   (*info->fprintf_func) (info->stream, "-%s",
+                                          reg_names[regno]);
+               }
+         }
+       else if (place == '3')
+         {
+           /* `fmovem' insn.  */
+           char doneany;
+           val = fetch_arg (buffer, place, 8, info);
+           if (val == 0)
+             {
+               (*info->fprintf_func) (info->stream, "#0");
+               break;
+             }
+           if (*d == 'l')
+             {
+               register int newval = 0;
+               for (regno = 0; regno < 8; ++regno)
+                 if (val & (0x80 >> regno))
+                   newval |= 1 << regno;
+               val = newval;
+             }
+           val &= 0xff;
+           doneany = 0;
+           for (regno = 0; regno < 8; ++regno)
+             if (val & (1 << regno))
+               {
+                 int first_regno;
+                 if (doneany)
+                   (*info->fprintf_func) (info->stream, "/");
+                 doneany = 1;
+                 (*info->fprintf_func) (info->stream, "fp%d", regno);
+                 first_regno = regno;
+                 while (val & (1 << (regno + 1)))
+                   ++regno;
+                 if (regno > first_regno)
+                   (*info->fprintf_func) (info->stream, "-fp%d", regno);
+               }
+         }
+       else
+         goto de_fault;
+      break;
+
+    default:  de_fault:
+      m68k_opcode_error (info, *d, ' ');
+    }
+
+  return (unsigned char *) p;
+}
+
+/* Fetch BITS bits from a position in the instruction specified by CODE.
+   CODE is a "place to put an argument", or 'x' for a destination
+   that is a general address (mode and register).
+   BUFFER contains the instruction.  */
+
+static int
+fetch_arg (buffer, code, bits, info)
+     unsigned char *buffer;
+     int code;
+     int bits;
+     disassemble_info *info;
+{
+  register int val = 0;
+  switch (code)
+    {
+    case 's':
+      val = buffer[1];
+      break;
+
+    case 'd':                  /* Destination, for register or quick.  */
+      val = (buffer[0] << 8) + buffer[1];
+      val >>= 9;
+      break;
+
+    case 'x':                  /* Destination, for general arg */
+      val = (buffer[0] << 8) + buffer[1];
+      val >>= 6;
+      break;
+
+    case 'k':
+      FETCH_DATA (info, buffer + 3);
+      val = (buffer[3] >> 4);
+      break;
+
+    case 'C':
+      FETCH_DATA (info, buffer + 3);
+      val = buffer[3];
+      break;
+
+    case '1':
+      FETCH_DATA (info, buffer + 3);
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 12;
+      break;
+
+    case '2':
+      FETCH_DATA (info, buffer + 3);
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 6;
+      break;
+
+    case '3':
+    case 'j':
+      FETCH_DATA (info, buffer + 3);
+      val = (buffer[2] << 8) + buffer[3];
+      break;
+
+    case '4':
+      FETCH_DATA (info, buffer + 5);
+      val = (buffer[4] << 8) + buffer[5];
+      val >>= 12;
+      break;
+
+    case '5':
+      FETCH_DATA (info, buffer + 5);
+      val = (buffer[4] << 8) + buffer[5];
+      val >>= 6;
+      break;
+
+    case '6':
+      FETCH_DATA (info, buffer + 5);
+      val = (buffer[4] << 8) + buffer[5];
+      break;
+
+    case '7':
+      FETCH_DATA (info, buffer + 3);
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 7;
+      break;
+      
+    case '8':
+      FETCH_DATA (info, buffer + 3);
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 10;
+      break;
+
+    case '9':
+      FETCH_DATA (info, buffer + 3);
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 5;
+      break;
+
+    case 'e':
+      val = (buffer[1] >> 6);
+      break;
+
+    default:
+      abort ();
+    }
+
+  switch (bits)
+    {
+    case 2:
+      return val & 3;
+    case 3:
+      return val & 7;
+    case 4:
+      return val & 017;
+    case 5:
+      return val & 037;
+    case 6:
+      return val & 077;
+    case 7:
+      return val & 0177;
+    case 8:
+      return val & 0377;
+    case 12:
+      return val & 07777;
+    default:
+      abort ();
+    }
+}
+
+/* Print an indexed argument.  The base register is BASEREG (-1 for pc).
+   P points to extension word, in buffer.
+   ADDR is the nominal core address of that extension word.  */
+
+static unsigned char *
+print_indexed (basereg, p, addr, info)
+     int basereg;
+     unsigned char *p;
+     bfd_vma addr;
+     disassemble_info *info;
+{
+  register int word;
+  static char *scales[] = {"", "*2", "*4", "*8"};
+  register int base_disp;
+  register int outer_disp;
+  char buf[40];
+
+  word = NEXTWORD (p);
+
+  /* Generate the text for the index register.
+     Where this will be output is not yet determined.  */
+  sprintf (buf, "[%s.%c%s]",
+          reg_names[(word >> 12) & 0xf],
+          (word & 0x800) ? 'l' : 'w',
+          scales[(word >> 9) & 3]);
+
+  /* Handle the 68000 style of indexing.  */
+
+  if ((word & 0x100) == 0)
+    {
+      print_base (basereg,
+                 ((word & 0x80) ? word | 0xff00 : word & 0xff)
+                 + ((basereg == -1) ? addr : 0),
+                 info);
+      (*info->fprintf_func) (info->stream, "%s", buf);
+      return p;
+    }
+
+  /* Handle the generalized kind.  */
+  /* First, compute the displacement to add to the base register.  */
+
+  if (word & 0200)
+    basereg = -2;
+  if (word & 0100)
+    buf[0] = 0;
+  base_disp = 0;
+  switch ((word >> 4) & 3)
+    {
+    case 2:
+      base_disp = NEXTWORD (p);
+      break;
+    case 3:
+      base_disp = NEXTLONG (p);
+    }
+  if (basereg == -1)
+    base_disp += addr;
+
+  /* Handle single-level case (not indirect) */
+
+  if ((word & 7) == 0)
+    {
+      print_base (basereg, base_disp, info);
+      (*info->fprintf_func) (info->stream, "%s", buf);
+      return p;
+    }
+
+  /* Two level.  Compute displacement to add after indirection.  */
+
+  outer_disp = 0;
+  switch (word & 3)
+    {
+    case 2:
+      outer_disp = NEXTWORD (p);
+      break;
+    case 3:
+      outer_disp = NEXTLONG (p);
+    }
+
+  (*info->fprintf_func) (info->stream, "%d(", outer_disp);
+  print_base (basereg, base_disp, info);
+
+  /* If postindexed, print the closeparen before the index.  */
+  if (word & 4)
+    (*info->fprintf_func) (info->stream, ")%s", buf);
+  /* If preindexed, print the closeparen after the index.  */
+  else
+    (*info->fprintf_func) (info->stream, "%s)", buf);
+
+  return p;
+}
+
+/* Print a base register REGNO and displacement DISP, on INFO->STREAM.
+   REGNO = -1 for pc, -2 for none (suppressed).  */
+
+static void
+print_base (regno, disp, info)
+     int regno;
+     int disp;
+     disassemble_info *info;
+{
+  if (regno == -2)
+    (*info->fprintf_func) (info->stream, "%d", disp);
+  else if (regno == -1)
+    (*info->fprintf_func) (info->stream, "0x%x", (unsigned) disp);
+  else
+    (*info->fprintf_func) (info->stream, "%d(%s)", disp, reg_names[regno]);
+}
index 1be0fbd04ca30b6e282b3270d0d0b5516c703215..aaf2beb0cc291f0f5c2573af31e25b7700183b91 100644 (file)
@@ -18,9 +18,9 @@ You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
+#include <ansidecl.h>
 #include "sysdep.h"
-#include <stdio.h>
-#include "bfd.h"
+#include "dis-asm.h"
 #include "opcode/mips.h"
 
 /* FIXME: we need direct access to the swapping functions.  */
@@ -60,122 +60,159 @@ extern int print_address PARAMS ((bfd_vma, FILE *));
 static CONST char * CONST reg_names[] = REGISTER_NAMES;
 \f
 /* subroutine */
-static unsigned char *
-print_insn_arg (d, l, stream, pc)
+static void
+print_insn_arg (d, l, pc, info)
      char *d;
-     register unsigned long int *l;
-     FILE *stream;
+     register unsigned long int l;
      bfd_vma pc;
+     struct disassemble_info *info;
 {
   switch (*d)
     {
     case ',':
     case '(':
     case ')':
-      fputc (*d, stream);
+      (*info->fprintf_func) (info->stream, "%c", *d);
       break;
 
     case 's':
-      fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rs]);
+      (*info->fprintf_func) (info->stream, "$%s",
+                            reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
       break;
 
     case 't':
-      fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rt]);
+      (*info->fprintf_func) (info->stream, "$%s",
+                            reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
       break;
 
     case 'i':
-      fprintf (stream, "%d", ((struct op_i_fmt *) l)->immediate);
+      (*info->fprintf_func) (info->stream, "%d",
+                       (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
       break;
 
     case 'j': /* same as i, but sign-extended */
-      fprintf (stream, "%d", ((struct op_b_fmt *) l)->delta);
+      (*info->fprintf_func) (info->stream, "%d",
+                            (l >> OP_SH_DELTA) & OP_MASK_DELTA);
       break;
 
     case 'a':
-      print_address ((pc & 0xF0000000) | (((struct op_j_fmt *)l)->target << 2),
-                    stream);
+      print_address (((pc & 0xF0000000)
+                     | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
+                    info->stream);
       break;
 
     case 'b':
-      print_address ((((struct op_b_fmt *) l)->delta << 2) + pc + 4, stream);
+      print_address ((((l >> OP_SH_DELTA) & OP_MASK_DELTA) << 2) + pc + 4,
+                    info->stream);
       break;
 
     case 'd':
-      fprintf (stream, "$%s", reg_names[((struct op_r_fmt *) l)->rd]);
+      (*info->fprintf_func) (info->stream, "$%s",
+                            reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
       break;
 
     case 'h':
-      fprintf (stream, "0x%x", ((struct op_r_fmt *) l)->shamt);
+      (*info->fprintf_func) (info->stream, "0x%x",
+                            (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
       break;
 
     case 'B':
-      fprintf (stream, "0x%x", ((struct op_brk_fmt *) l)->code);
+      (*info->fprintf_func) (info->stream, "0x%x",
+                            (l >> OP_SH_CODE) & OP_MASK_CODE);
       break;
 
     case 'S':
-      fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fs);
+      (*info->fprintf_func) (info->stream, "$f%d",
+                            (l >> OP_SH_FS) & OP_MASK_FS);
       break;
 
     case 'T':
-      fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->ft);
+      (*info->fprintf_func) (info->stream, "$f%d",
+                            (l >> OP_SH_FT) & OP_MASK_FT);
       break;
 
     case 'D':
-      fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fd);
+      (*info->fprintf_func) (info->stream, "$f%d",
+                            (l >> OP_SH_FD) & OP_MASK_FD);
       break;
 
     default:
-      fprintf (stream, "# internal error, undefined modifier(%c)", *d);
+      (*info->fprintf_func) (info->stream,
+                            "# internal error, undefined modifier(%c)", *d);
       break;
     }
 }
 \f
 /* Print the mips instruction at address MEMADDR in debugged memory,
-   on STREAM.  Returns length of the instruction, in bytes, which is
+   on using INFO.  Returns length of the instruction, in bytes, which is
    always 4.  BIGENDIAN must be 1 if this is big-endian code, 0 if
    this is little-endian code.  */
 
 int
-print_insn_mips (memaddr, buffer, stream, bigendian)
+_print_insn_mips (memaddr, word, info)
      bfd_vma memaddr;
-     bfd_byte *buffer;
-     FILE *stream;
-     int bigendian;
+     struct disassemble_info *info;
+     unsigned long int word;
 {
   register int i;
   register char *d;
-  unsigned long int l;
-
-  /* FIXME: can't we export these functions from bfd?  */
-  if (bigendian)
-    l = _do_getb32 (buffer);
-  else
-    l = _do_getl32 (buffer);
 
   for (i = 0; i < NOPCODES; i++)
     {
       register unsigned int opcode = mips_opcodes[i].opcode;
       register unsigned int match = mips_opcodes[i].match;
-      if ((l & match) == opcode)
+      if ((word & match) == opcode)
        break;
     }
 
   /* Handle undefined instructions.  */
   if (i == NOPCODES)
     {
-      fprintf (stream, "0x%x",l);
+      (*info->fprintf_func) (info->stream, "0x%x", word);
       return 4;
     }
 
-  fprintf (stream, "%s", mips_opcodes[i].name);
+  (*info->fprintf_func) (info->stream, "%s", mips_opcodes[i].name);
 
   if (!(d = mips_opcodes[i].args))
     return 4;
 
-  fputc (' ', stream);
+  (*info->fprintf_func) (info->stream, " ");
 
   while (*d)
-    print_insn_arg (d++, &l, stream, memaddr);
+    print_insn_arg (d++, word, memaddr, info);
 
   return 4;
 }
+
+int
+print_insn_big_mips (memaddr, info)
+     bfd_vma memaddr;
+     struct disassemble_info *info;
+{
+  bfd_byte buffer[4];
+  int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+  if (status == 0)
+    return _print_insn_mips (memaddr, _do_getb32 (buffer), info);
+  else
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+}
+
+int
+print_insn_little_mips (memaddr, info)
+     bfd_vma memaddr;
+     struct disassemble_info *info;
+{
+  bfd_byte buffer[4];
+  int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+  if (status == 0)
+    return _print_insn_mips (memaddr, _do_getl32 (buffer), info);
+  else
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+}
index 2a2d3c343b00b1b65e5addb812b459bfa961d4bb..d296f64c3dc6145b48ebb45ef8ecdc74bbe07aeb 100644 (file)
-#include <stdio.h>
+/*
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include "sysdep.h"
+#include "dis-asm.h"
+
 #define DEFINE_TABLE
 #include "z8k-opc.h"
 
-static void fetch_data();
-static void fetch_instr();
-static unsigned long get_val();
-static int is_segmented();
-static int lookup_instr();
-static void output_instr();
-static void unpack_instr();
-static void unparse_instr();
-
-typedef struct {
-   unsigned char instr_buf[24];
-   unsigned long bytes_fetched;
-   unsigned long tabl_index;
-   char instr_asmsrc[80];
-   unsigned long arg_reg[0x0f];
-   unsigned long immediate;
-   unsigned long displacement;
-   unsigned long address;
-   unsigned long cond_code;
-   unsigned long ctrl_code;
-   unsigned long flags;
-   unsigned long interrupts;
-} instr_data_s;
-
-
-static char *codes[16] = 
+\f
+#include <setjmp.h>
+
+\f
+typedef struct
+{
+  /* These are all indexed by nibble number (i.e only every other entry
+     of bytes is used, and every 4th entry of words).  */
+  unsigned char nibbles[24];
+  unsigned char bytes[24];
+  unsigned short words[24];
+
+  /* Nibble number of first word not yet fetched.  */
+  int max_fetched;
+  bfd_vma insn_start;
+  jmp_buf bailout;
+
+  long tabl_index;
+  char instr_asmsrc[80];
+  unsigned long arg_reg[0x0f];
+  unsigned long immediate;
+  unsigned long displacement;
+  unsigned long address;
+  unsigned long cond_code;
+  unsigned long ctrl_code;
+  unsigned long flags;
+  unsigned long interrupts;
+}
+instr_data_s;
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
+   on error.  */
+#define FETCH_DATA(info, nibble) \
+  ((nibble) <= ((instr_data_s *)(info->private_data))->max_fetched \
+   ? 1 : fetch_data ((info), (nibble)))
+
+static int
+fetch_data (info, nibble)
+     struct disassemble_info *info;
+     int nibble;
+{
+  char mybuf[20];
+  int status;
+  instr_data_s *priv = (instr_data_s *)info->private_data;
+  bfd_vma start = priv->insn_start + priv->max_fetched / 2;
+
+  if ((nibble % 4) != 0)
+    abort ();
+  status = (*info->read_memory_func) (start,
+                                     mybuf,
+                                     (nibble - priv->max_fetched) / 2,
+                                     info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, start, info);
+      longjmp (priv->bailout);
+    }
+
+  {
+    int i;
+    char *p = mybuf + priv->max_fetched / 2;
+    
+    for (i = priv->max_fetched; i < nibble;)
+      {
+       priv->words[i] = (p[0] << 8) | p[1];
+       
+       priv->bytes[i] = *p;
+       priv->nibbles[i++] = *p >> 4;
+       priv->nibbles[i++] = *p &0xf;
+
+       ++p;
+       priv->bytes[i] = *p;
+       priv->nibbles[i++] = *p >> 4;
+       priv->nibbles[i++] = *p & 0xf;
+
+       ++p;
+      }
+  }
+  priv->max_fetched = nibble;
+  return 1;
+}
+
+static char *codes[16] =
 {
   "f",
   "lt",
@@ -47,473 +125,445 @@ static char *codes[16] =
   "nc/uge"
 };
 
-
-int print_insn_z8k(addr, in_buf, stream)
-unsigned long addr;
-unsigned char *in_buf;
-FILE *stream;
+int z8k_lookup_instr PARAMS ((unsigned char*, disassemble_info *));
+static void output_instr
+  PARAMS ((instr_data_s *, unsigned long, disassemble_info *));
+static void unpack_instr PARAMS ((instr_data_s *, int, disassemble_info *));
+static void unparse_instr PARAMS ((instr_data_s *));
+
+static int
+print_insn_z8k (addr, info, is_segmented)
+     unsigned long addr;
+     disassemble_info *info;
+     int is_segmented;
 {
-  instr_data_s  instr_data;
+  instr_data_s instr_data;
 
-  fetch_instr( &in_buf, &instr_data );
-  if (  lookup_instr( &instr_data )) 
-  {
-    fetch_data( &in_buf, &instr_data );
-    unpack_instr( &instr_data );
-    unparse_instr( &instr_data );
-    output_instr( &instr_data, addr, stream );
-    return instr_data.bytes_fetched;
-  }
-  else {
-    fprintf(stream,".word %02x%02x", in_buf[0], in_buf[1]);
-    return 2;
-  }
-
-}
-
-
-static void fetch_data( in_buf, instr_data )
-unsigned char **in_buf;
-instr_data_s *instr_data;
-{
-   int bytes_2fetch;
-
-   bytes_2fetch = z8k_table[instr_data->tabl_index].length -
-                  instr_data->bytes_fetched;
-   while( bytes_2fetch-- )
-      instr_data->instr_buf[instr_data->bytes_fetched++] = *(*in_buf)++;
-}
-
-static void fetch_instr( in_buf, instr_data )
-unsigned char **in_buf;
-instr_data_s  *instr_data;
-{
-   unsigned int loop = 2;
-
-   instr_data->bytes_fetched = 0;
-   while( loop-- )
-      instr_data->instr_buf[instr_data->bytes_fetched++] = *(*in_buf)++;
+  info->private_data = (PTR) &instr_data;
+  instr_data.max_fetched = 0;
+  instr_data.insn_start = addr;
+  if (setjmp (instr_data.bailout) != 0)
+    /* Error return.  */
+    return -1;
 
+  instr_data.tabl_index = z8k_lookup_instr (instr_data.nibbles, info);
+  if (instr_data.tabl_index > 0)
+    {
+      unpack_instr (&instr_data, is_segmented, info);
+      unparse_instr (&instr_data);
+      output_instr (&instr_data, addr, info);
+      return z8k_table[instr_data.tabl_index].length;
+    }
+  else
+    {
+      FETCH_DATA (info, 4);
+      (*info->fprintf_func) (info->stream, ".word %02x%02x",
+                            instr_data.bytes[0], instr_data.bytes[2]);
+      return 2;
+    }
 }
 
-static unsigned long get_val( instr_buf, start_nibl, nibls_long )
-unsigned char (*instr_buf)[];
-unsigned int start_nibl, nibls_long;
+print_insn_z8001 (addr, info)
+     unsigned long addr;
+     disassemble_info *info;
 {
-   unsigned long ret_val;
-   unsigned char byte_val, nibl_val;
-   unsigned int  nibl_index, nibl_lim;
-   unsigned int byte_index;
-   unsigned int which_nibl;
-
-   ret_val = 0;
-   nibl_lim = start_nibl + nibls_long;
-   for( nibl_index = start_nibl; nibl_index < nibl_lim; nibl_index++ )
-   {
-      byte_index = nibl_index / 2;
-      which_nibl = nibl_index % 2;
-      switch( which_nibl )
-      {
-         case 0:
-            byte_val = (*instr_buf)[byte_index];
-            nibl_val = (byte_val >> 4) & 0x0f;
-            break;
-         case 1:
-            nibl_val = byte_val & 0x0f;
-            break;
-      }
-      ret_val = (ret_val << 4) | nibl_val;
-   }
-
-   return ret_val;
-
+  return print_insn_z8k (addr, info, 1);
 }
 
-static int is_segmented()
+print_insn_z8002 (addr, info)
+     unsigned long addr;
+     disassemble_info *info;
 {
-   return 1;
+  return print_insn_z8k (addr, info, 0);
 }
 
-static 
-int lookup_instr( instr_data )
-instr_data_s *instr_data;
+int
+z8k_lookup_instr (nibbles, info)
+     unsigned char *nibbles;
+     disassemble_info *info;
 {
 
-  int            nibl_index, tabl_index;
-  int            tablent_found, nibl_matched;
+  int nibl_index, tabl_index;
+  int nibl_matched;
   unsigned short instr_nibl;
   unsigned short tabl_datum, datum_class, datum_value;
 
   nibl_matched = 0;
   tabl_index = 0;
-  while( ! nibl_matched && z8k_table[tabl_index].name)
-  {
-    nibl_matched = 1;
-    for( nibl_index = 0; nibl_index < 4 && nibl_matched; nibl_index++ )
+  while (!nibl_matched && z8k_table[tabl_index].name)
     {
-      instr_nibl =  get_val( instr_data->instr_buf, nibl_index, 1 );
-
-      tabl_datum = z8k_table[tabl_index].byte_info[nibl_index];
-      datum_class = tabl_datum & CLASS_MASK;
-      datum_value = ~CLASS_MASK & tabl_datum;
-
-      switch( datum_class )
-      {
-       case CLASS_BIT:
-       if( datum_value != instr_nibl ) nibl_matched = 0;
-       break;
-       case CLASS_00II:
-       if( ! ((~instr_nibl) & 0x4) ) nibl_matched = 0;
-       break;
-       case CLASS_01II:
-       if( ! (instr_nibl & 0x4) ) nibl_matched = 0;
-       break;
-       case CLASS_0CCC:
-       if( ! ((~instr_nibl) & 0x8) ) nibl_matched = 0;
-       break;
-       case CLASS_1CCC:
-       if( ! (instr_nibl & 0x8) ) nibl_matched = 0;
-       break;
-       case CLASS_0DISP7:
-       if( ! ((~instr_nibl) & 0x8) ) nibl_matched = 0;
-       nibl_index += 1;
-       break;
-       case CLASS_1DISP7:
-       if( ! (instr_nibl & 0x8) ) nibl_matched = 0;
-       nibl_index += 1;
-       break;
-       case CLASS_REGN0:
-       if( instr_nibl == 0 ) nibl_matched = 0;
-       break;
-       default:
-       break;
-      }
+      nibl_matched = 1;
+      for (nibl_index = 0; nibl_index < z8k_table[tabl_index].length * 2 && nibl_matched; nibl_index++)
+       {
+         if ((nibl_index % 4) == 0)
+           /* Fetch one word at a time.  */
+           FETCH_DATA (info, nibl_index + 4);
+         instr_nibl = nibbles[nibl_index];
+
+         tabl_datum = z8k_table[tabl_index].byte_info[nibl_index];
+         datum_class = tabl_datum & CLASS_MASK;
+         datum_value = ~CLASS_MASK & tabl_datum;
+
+         switch (datum_class)
+           {
+           case CLASS_BIT:
+             if (datum_value != instr_nibl)
+               nibl_matched = 0;
+             break;
+           case CLASS_00II:
+             if (!((~instr_nibl) & 0x4))
+               nibl_matched = 0;
+             break;
+           case CLASS_01II:
+             if (!(instr_nibl & 0x4))
+               nibl_matched = 0;
+             break;
+           case CLASS_0CCC:
+             if (!((~instr_nibl) & 0x8))
+               nibl_matched = 0;
+             break;
+           case CLASS_1CCC:
+             if (!(instr_nibl & 0x8))
+               nibl_matched = 0;
+             break;
+           case CLASS_0DISP7:
+             if (!((~instr_nibl) & 0x8))
+               nibl_matched = 0;
+             nibl_index += 1;
+             break;
+           case CLASS_1DISP7:
+             if (!(instr_nibl & 0x8))
+               nibl_matched = 0;
+             nibl_index += 1;
+             break;
+           case CLASS_REGN0:
+             if (instr_nibl == 0)
+               nibl_matched = 0;
+             break;
+           case CLASS_BIT_1OR2:
+             if ((instr_nibl | 0x2) != (datum_value | 0x2))
+               nibl_matched = 0;
+             break;
+           default:
+             break;
+           }
+       }
+      if (nibl_matched)
+       {
+         return tabl_index;
+       }
+
+      tabl_index++;
     }
-    tabl_index++;
-  }
-
-
-  instr_data->tabl_index = tabl_index;
-
-  return   nibl_matched;
+  return -1;
 
 }
 
-static void output_instr( instr_data, addr, stream )
-instr_data_s  *instr_data;
-unsigned long addr;
-FILE *stream;
+static void
+output_instr (instr_data, addr, info)
+     instr_data_s *instr_data;
+     unsigned long addr;
+     disassemble_info *info;
 {
-   int            loop, loop_limit;
-   unsigned long  word_val;
-   char           tmp_str[20];
-   char           out_str[100];
+  int loop, loop_limit;
+  char tmp_str[20];
+  char out_str[100];
 
-   strcpy( out_str, "" );
+  strcpy (out_str, "\t");
 
-   loop_limit = z8k_table[instr_data->tabl_index].length / 2;
-   for( loop = 0; loop < loop_limit; loop++ )
-   {
-      word_val = get_val( instr_data->instr_buf, loop * 4, 4 );
-      sprintf( tmp_str,  "%04x ", word_val );
-      strcat( out_str, tmp_str );
-   }
+  loop_limit = z8k_table[instr_data->tabl_index].length * 2;
+  FETCH_DATA (info, loop_limit);
+  for (loop = 0; loop < loop_limit; loop++)
+    {
+      sprintf (tmp_str, "%x", instr_data->nibbles[loop]);
+      strcat (out_str, tmp_str);
+    }
 
-   while( loop++ < 5 )
-   {
-      strcat( out_str, "     " );
-   }
+  while (loop++ < 8)
+    {
+      strcat (out_str, " ");
+    }
 
-   strcat( out_str, instr_data->instr_asmsrc );
+  strcat (out_str, instr_data->instr_asmsrc);
 
-   fprintf( stream, "%s", out_str );
+  (*info->fprintf_func) (info->stream, "%s", out_str);
 }
 
-static void unpack_instr( instr_data )
-instr_data_s  *instr_data;
+static void
+unpack_instr (instr_data, is_segmented, info)
+     instr_data_s *instr_data;
+     int is_segmented;
+     disassemble_info *info;
 {
-   int            nibl_index, word_index;
-   int            nibl_count, loop;
-   unsigned short instr_nibl, instr_byte, instr_word, instr_long;
-   unsigned short tabl_datum, datum_class, datum_value;
-
-   nibl_count = 0;
-   loop = 0;
-   while( z8k_table[instr_data->tabl_index].byte_info[loop] != 0 )
-   {
-      word_index = (int) nibl_count / 4;
-      nibl_index = (int) nibl_count % 4;
-
-      switch( nibl_index )
-      {
-         case 0:
-            instr_nibl = get_val( instr_data->instr_buf, nibl_count, 1 );
-            instr_byte = get_val( instr_data->instr_buf, nibl_count, 2 );
-            instr_word = get_val( instr_data->instr_buf, nibl_count, 4 );
-            instr_long = get_val( instr_data->instr_buf, nibl_count, 8 );
-            break;
-         case 1:
-            instr_nibl = get_val( instr_data->instr_buf, nibl_count, 1 );
-            break;
-         case 2:
-            instr_nibl = get_val( instr_data->instr_buf, nibl_count, 1 );
-            instr_byte = get_val( instr_data->instr_buf, nibl_count, 2 );
-            break;
-         case 3:
-            instr_nibl = get_val( instr_data->instr_buf, nibl_count, 1 );
-            break;
-         default:
-            break;
-      }
+  int nibl_count, loop;
+  unsigned short instr_nibl, instr_byte, instr_word;
+  long instr_long;
+  unsigned short tabl_datum, datum_class, datum_value;
+
+  nibl_count = 0;
+  loop = 0;
+  while (z8k_table[instr_data->tabl_index].byte_info[loop] != 0)
+    {
+      FETCH_DATA (info, nibl_count + 4 - (nibl_count % 4));
+      instr_nibl = instr_data->nibbles[nibl_count];
+      instr_byte = instr_data->bytes[nibl_count];
+      instr_word = instr_data->words[nibl_count];
 
       tabl_datum = z8k_table[instr_data->tabl_index].byte_info[loop];
       datum_class = tabl_datum & CLASS_MASK;
       datum_value = tabl_datum & ~CLASS_MASK;
 
-      switch( datum_class )
-      {
-         case CLASS_X:
-            instr_data->address = instr_nibl;
-            break;
-         case CLASS_BA:
-            instr_data->displacement = instr_nibl;
-            break;
-         case CLASS_BX:
-            instr_data->arg_reg[datum_value] = instr_nibl;
-            break;
-         case CLASS_DISP:
-            switch( datum_value )
-            {
-               case ARG_DISP16:
-                  instr_data->displacement = instr_word;
-                  nibl_count += 3;
-                  break;
-               case ARG_DISP12:
-                  instr_data->displacement = instr_word & 0x0fff;
-                  nibl_count += 2;
-                  break;
-               default:
-                  break;
-            }
-            break;
-         case CLASS_IMM:
-            switch( datum_value )
-            {
-               case ARG_IMM4:
-                  instr_data->immediate = instr_nibl;
-                  break;
-               case ARG_IMM8:
-                  instr_data->immediate = instr_byte;
-                  nibl_count += 1;
-                  break;
-               case ARG_IMM16:
-                  instr_data->immediate = instr_word;
-                  nibl_count += 3;
-                  break;
-               case ARG_IMM32:
-                  instr_data->immediate = instr_long;
-                  nibl_count += 7;
-                  break;
-               case ARG_IMMN:
-                  instr_data->immediate = instr_nibl -1;
-                  break;
-               /* ????? */
-               /* missing ARG_IMMNMINUS1 */
-               case ARG_IMM_1:
-                  instr_data->immediate = 1;
-                  break;
-               case ARG_IMM_2:
-                  instr_data->immediate = 2;
-                  break;
-               case ARG_NIM16:
-                  instr_data->immediate = (- instr_word);
-                  nibl_count += 3;
-                  break;
-               case ARG_IMM2:
-                  instr_data->immediate = instr_nibl & 0x3;
-                  break;
-               default:
-                  break;
-            }
-            break;
-         case CLASS_CC:
-            instr_data->cond_code = instr_nibl;
-            break;
-         case CLASS_CTRL:
-            instr_data->ctrl_code = instr_nibl;
-            break;
-         case CLASS_DA:
-         case CLASS_ADDRESS:
-            if( is_segmented() )
-            {
-               if( instr_nibl & 0x8 )
-               {
-                  instr_data->address = ((instr_word & 0x7f00) << 8) +
-                                        (instr_long & 0xffff);
-                  nibl_count += 7;
-               }
-               else
-               {
-                  instr_data->address = ((instr_word & 0x7f00) << 8) +
-                                        (instr_word  & 0x00ff);
-                  nibl_count += 3;
-               }
-            }
-            else
-            {
-               instr_data->address = instr_word;
-               nibl_count += 3;
-            }
-            break;
-         case CLASS_0CCC:
-            instr_data->cond_code = instr_nibl & 0x7;
-            break;
-         case CLASS_1CCC:
-            instr_data->cond_code = instr_nibl & 0x7;
-            break;
-         case CLASS_0DISP7:
-            instr_data->displacement = instr_byte & 0x7f;
-            nibl_count += 1;
-            break;
-         case CLASS_1DISP7:
-            instr_data->displacement = instr_byte & 0x7f;
-            nibl_count += 1;
-            break;
-         case CLASS_01II:
-            instr_data->interrupts = instr_nibl & 0x3;
-            break;
-         case CLASS_00II:
-            instr_data->interrupts = instr_nibl & 0x3;
-            break;
-         case CLASS_BIT:
-            /* do nothing */
-            break;
-         case CLASS_IR:
-            instr_data->arg_reg[datum_value] = instr_nibl;
-            break;
-         case CLASS_FLAGS:
-            instr_data->flags = instr_nibl;
-            break;
-         case CLASS_REG:
-            instr_data->arg_reg[datum_value] = instr_nibl;
-            break;
-         case CLASS_REG_BYTE:
-            instr_data->arg_reg[datum_value] = instr_nibl;
-            break;
-         case CLASS_REG_WORD:
-            instr_data->arg_reg[datum_value] = instr_nibl;
-            break;
-         case CLASS_REG_QUAD:
-            instr_data->arg_reg[datum_value] = instr_nibl;
-            break;
-         case CLASS_REG_LONG:
-            instr_data->arg_reg[datum_value] = instr_nibl;
-            break;
-         case CLASS_REGN0:
-            instr_data->arg_reg[datum_value] = instr_nibl;
-            break;
-         default:
-            break;
-      }
+      switch (datum_class)
+       {
+       case CLASS_X:
+         instr_data->address = instr_nibl;
+         break;
+       case CLASS_BA:
+         instr_data->displacement = instr_nibl;
+         break;
+       case CLASS_BX:
+         instr_data->arg_reg[datum_value] = instr_nibl;
+         break;
+       case CLASS_DISP:
+         switch (datum_value)
+           {
+           case ARG_DISP16:
+             instr_data->displacement = instr_word;
+             nibl_count += 3;
+             break;
+           case ARG_DISP12:
+             instr_data->displacement = instr_word & 0x0fff;
+             nibl_count += 2;
+             break;
+           default:
+             break;
+           }
+         break;
+       case CLASS_IMM:
+         switch (datum_value)
+           {
+           case ARG_IMM4:
+             instr_data->immediate = instr_nibl;
+             break;
+           case ARG_NIM8:
+             instr_data->immediate = (-instr_byte);
+             nibl_count += 1;
+             break;
+           case ARG_IMM8:
+             instr_data->immediate = instr_byte;
+             nibl_count += 1;
+             break;
+           case ARG_IMM16:
+             instr_data->immediate = instr_word;
+             nibl_count += 3;
+             break;
+           case ARG_IMM32:
+             FETCH_DATA (info, nibl_count + 8);
+             instr_long = (instr_data->words[nibl_count] << 16)
+               | (instr_data->words[nibl_count + 4]);
+             instr_data->immediate = instr_long;
+             nibl_count += 7;
+             break;
+           case ARG_IMMN:
+             instr_data->immediate = instr_nibl - 1;
+             break;
+             /* ????? */
+             /* missing ARG_IMMNMINUS1 */
+           case ARG_IMM_1:
+             instr_data->immediate = 1;
+             break;
+           case ARG_IMM_2:
+             instr_data->immediate = 2;
+             break;
+           case ARG_IMM2:
+             instr_data->immediate = instr_nibl & 0x3;
+             break;
+           default:
+             break;
+           }
+         break;
+       case CLASS_CC:
+         instr_data->cond_code = instr_nibl;
+         break;
+       case CLASS_CTRL:
+         instr_data->ctrl_code = instr_nibl;
+         break;
+       case CLASS_DA:
+       case CLASS_ADDRESS:
+         if (is_segmented)
+           {
+             if (instr_nibl & 0x8)
+               {
+                 FETCH_DATA (info, nibl_count + 8);
+                 instr_long = (instr_data->words[nibl_count] << 16)
+                   | (instr_data->words[nibl_count + 4]);
+                 instr_data->address = ((instr_word & 0x7f00) << 8) +
+                   (instr_long & 0xffff);
+                 nibl_count += 7;
+               }
+             else
+               {
+                 instr_data->address = ((instr_word & 0x7f00) << 8) +
+                   (instr_word & 0x00ff);
+                 nibl_count += 3;
+               }
+           }
+         else
+           {
+             instr_data->address = instr_word;
+             nibl_count += 3;
+           }
+         break;
+       case CLASS_0CCC:
+         instr_data->cond_code = instr_nibl & 0x7;
+         break;
+       case CLASS_1CCC:
+         instr_data->cond_code = instr_nibl & 0x7;
+         break;
+       case CLASS_0DISP7:
+         instr_data->displacement = instr_byte & 0x7f;
+         nibl_count += 1;
+         break;
+       case CLASS_1DISP7:
+         instr_data->displacement = instr_byte & 0x7f;
+         nibl_count += 1;
+         break;
+       case CLASS_01II:
+         instr_data->interrupts = instr_nibl & 0x3;
+         break;
+       case CLASS_00II:
+         instr_data->interrupts = instr_nibl & 0x3;
+         break;
+       case CLASS_BIT:
+         /* do nothing */
+         break;
+       case CLASS_IR:
+         instr_data->arg_reg[datum_value] = instr_nibl;
+         break;
+       case CLASS_FLAGS:
+         instr_data->flags = instr_nibl;
+         break;
+       case CLASS_REG:
+         instr_data->arg_reg[datum_value] = instr_nibl;
+         break;
+       case CLASS_REG_BYTE:
+         instr_data->arg_reg[datum_value] = instr_nibl;
+         break;
+       case CLASS_REG_WORD:
+         instr_data->arg_reg[datum_value] = instr_nibl;
+         break;
+       case CLASS_REG_QUAD:
+         instr_data->arg_reg[datum_value] = instr_nibl;
+         break;
+       case CLASS_REG_LONG:
+         instr_data->arg_reg[datum_value] = instr_nibl;
+         break;
+       case CLASS_REGN0:
+         instr_data->arg_reg[datum_value] = instr_nibl;
+         break;
+       default:
+         break;
+       }
 
       loop += 1;
       nibl_count += 1;
-   }
+    }
 }
 
-static void unparse_instr( instr_data )
-instr_data_s  *instr_data;
+static void
+unparse_instr (instr_data)
+     instr_data_s *instr_data;
 {
-   unsigned short tabl_datum, datum_class, datum_value;
-   int            loop, loop_limit;
-   char           out_str[80], tmp_str[25];
+  unsigned short tabl_datum, datum_class, datum_value;
+  int loop, loop_limit;
+  char out_str[80], tmp_str[25];
 
-   sprintf( out_str, "\t%s\t", z8k_table[instr_data->tabl_index].name );
+  sprintf (out_str, "\t%s\t", z8k_table[instr_data->tabl_index].name);
 
-   loop_limit = z8k_table[instr_data->tabl_index].noperands;
-   for( loop = 0; loop < loop_limit; loop++ )
-   {
-      if( loop )
-         strcat( out_str, "," );
+  loop_limit = z8k_table[instr_data->tabl_index].noperands;
+  for (loop = 0; loop < loop_limit; loop++)
+    {
+      if (loop)
+       strcat (out_str, ",");
 
       tabl_datum = z8k_table[instr_data->tabl_index].arg_info[loop];
       datum_class = tabl_datum & CLASS_MASK;
       datum_value = tabl_datum & ~CLASS_MASK;
 
-      switch( datum_class )
-      {
-         case CLASS_X:
-            sprintf( tmp_str, "0x%0x(R%d)", instr_data->address,
-                     instr_data->arg_reg[datum_value] );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_BA:
-            sprintf( tmp_str, "r%d(#%x)", instr_data->arg_reg[datum_value],
-                     instr_data->displacement);
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_BX:
-            sprintf( tmp_str, "r%d(R%d)", instr_data->arg_reg[datum_value],
-                     instr_data->arg_reg[ARG_RX] );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_DISP:
-            sprintf( tmp_str, "#0x%0x", instr_data->displacement );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_IMM:
-            sprintf( tmp_str, "#0x%0x", instr_data->immediate );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_CC:
-            sprintf( tmp_str, "%s", codes[instr_data->cond_code] );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_CTRL:
-            sprintf( tmp_str, "0x%0x", instr_data->ctrl_code );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_DA:
-         case CLASS_ADDRESS:
-            sprintf( tmp_str, "#0x%0x", instr_data->address );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_IR:
-            sprintf( tmp_str, "@R%d", instr_data->arg_reg[datum_value] );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_FLAGS:
-            sprintf( tmp_str, "0x%0x", instr_data->flags );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_REG_BYTE:
-            if( instr_data->arg_reg[datum_value] >= 0x8 )
-            {
-               sprintf( tmp_str, "rl%d",
-                        instr_data->arg_reg[datum_value] - 0x8 );
-            }
-            else
-            {
-               sprintf( tmp_str, "rh%d", instr_data->arg_reg[datum_value] );
-            } 
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_REG_WORD:
-            sprintf( tmp_str, "r%d", instr_data->arg_reg[datum_value] );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_REG_QUAD:
-            sprintf( tmp_str, "rq%d", instr_data->arg_reg[datum_value] );
-            strcat( out_str, tmp_str );
-            break;
-         case CLASS_REG_LONG:
-            sprintf( tmp_str, "rr%d", instr_data->arg_reg[datum_value] );
-            strcat( out_str, tmp_str );
-            break;
-         default:
-            break;
-      }
-   }
+      switch (datum_class)
+       {
+       case CLASS_X:
+         sprintf (tmp_str, "0x%0x(R%d)", instr_data->address,
+                  instr_data->arg_reg[datum_value]);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_BA:
+         sprintf (tmp_str, "r%d(#%x)", instr_data->arg_reg[datum_value],
+                  instr_data->immediate);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_BX:
+         sprintf (tmp_str, "r%d(R%d)", instr_data->arg_reg[datum_value],
+                  instr_data->arg_reg[ARG_RX]);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_DISP:
+         sprintf (tmp_str, "#0x%0x", instr_data->displacement);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_IMM:
+         sprintf (tmp_str, "#0x%0x", instr_data->immediate);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_CC:
+         sprintf (tmp_str, "%s", codes[instr_data->cond_code]);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_CTRL:
+         sprintf (tmp_str, "0x%0x", instr_data->ctrl_code);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_DA:
+       case CLASS_ADDRESS:
+         sprintf (tmp_str, "#0x%0x", instr_data->address);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_IR:
+         sprintf (tmp_str, "@R%d", instr_data->arg_reg[datum_value]);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_FLAGS:
+         sprintf (tmp_str, "0x%0x", instr_data->flags);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_REG_BYTE:
+         if (instr_data->arg_reg[datum_value] >= 0x8)
+           {
+             sprintf (tmp_str, "rl%d",
+                      instr_data->arg_reg[datum_value] - 0x8);
+           }
+         else
+           {
+             sprintf (tmp_str, "rh%d", instr_data->arg_reg[datum_value]);
+           }
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_REG_WORD:
+         sprintf (tmp_str, "r%d", instr_data->arg_reg[datum_value]);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_REG_QUAD:
+         sprintf (tmp_str, "rq%d", instr_data->arg_reg[datum_value]);
+         strcat (out_str, tmp_str);
+         break;
+       case CLASS_REG_LONG:
+         sprintf (tmp_str, "rr%d", instr_data->arg_reg[datum_value]);
+         strcat (out_str, tmp_str);
+         break;
+       default:
+         break;
+       }
+    }
 
-   strcpy( instr_data->instr_asmsrc, out_str );
+  strcpy (instr_data->instr_asmsrc, out_str);
 }