* m88k-dis.c: New file, moved in from gdb and changed to use the
authorIan Lance Taylor <ian@airs.com>
Thu, 15 Jul 1993 16:40:49 +0000 (16:40 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 15 Jul 1993 16:40:49 +0000 (16:40 +0000)
new dis-asm.h disassembler interface.
* Makefile.in (DIS_LIBS): Added m88k-dis.o.
(m88k-dis.o): New target.

opcodes/.Sanitize
opcodes/ChangeLog
opcodes/Makefile.in
opcodes/m88k-dis.c [new file with mode: 0644]

index a73b2d6..a10b965 100644 (file)
@@ -38,6 +38,7 @@ i386-dis.c
 i960-dis.c
 m68881-ext.c
 m68k-dis.c
+m88k-dis.c
 mips-dis.c
 sh-opc.h
 sh-dis.c
index 9f7deaa..d4dce91 100644 (file)
@@ -1,3 +1,10 @@
+Thu Jul 15 12:37:05 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * m88k-dis.c: New file, moved in from gdb and changed to use the
+       new dis-asm.h disassembler interface.
+       * Makefile.in (DIS_LIBS): Added m88k-dis.o.
+       (m88k-dis.o): New target.
+
 Tue Jul 13 10:04:16 1993  Ian Lance Taylor  (ian@cygnus.com)
 
        * mips-dis.c (print_insn_arg, _print_insn_mips): Made pointer to
index d550dc9..fee9aab 100644 (file)
@@ -63,8 +63,10 @@ TARGETLIB = libopcodes.a
 
 # To circumvent a Sun make VPATH bug, each file listed here
 # should also have a foo.o: foo.c line further along in this file.
-DIS_LIBS = i386-dis.o z8k-dis.o m68k-dis.o mips-dis.o h8500-dis.o h8300-dis.o dis-buf.o \
-       sparc-dis.o a29k-dis.o i960-dis.o alpha-dis.o sh-dis.o hppa-dis.o
+
+DIS_LIBS = i386-dis.o z8k-dis.o m68k-dis.o mips-dis.o h8500-dis.o \
+       h8300-dis.o dis-buf.o sparc-dis.o a29k-dis.o i960-dis.o \
+       alpha-dis.o sh-dis.o hppa-dis.o m88k-dis.o
 
 OFILES = $(DIS_LIBS) sparc-opc.o m68881-ext.o
 #### host and target dependent Makefile fragments come in here.
@@ -128,6 +130,7 @@ z8k-dis.o: z8k-dis.c z8k-opc.h $(INCDIR)/dis-asm.h
 sh-dis.o: sh-dis.c sh-opc.h $(INCDIR)/dis-asm.h
 alpha-dis.o: alpha-dis.c alpha-opc.h $(INCDIR)/dis-asm.h
 hppa-dis.o: hppa-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/hppa.h
+m88k-dis.o: m88k-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/m88k.h
 
 tags etags: TAGS
 
diff --git a/opcodes/m88k-dis.c b/opcodes/m88k-dis.c
new file mode 100644 (file)
index 0000000..fec9559
--- /dev/null
@@ -0,0 +1,321 @@
+/* Print instructions for the Motorola 88000, for GDB and GNU Binutils.
+   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1993
+   Free Software Foundation, Inc.
+   Contributed by Data General Corporation, November 1989.
+   Partially derived from an earlier printcmd.c.
+
+This file is part of GDB and the 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 "dis-asm.h"
+#include "opcode/m88k.h"
+
+/* FIXME: Uses the internal bfd swapping routines.  */
+#include "libbfd.h"
+
+INSTAB  *hashtable[HASHVAL] = {0};
+
+static int
+m88kdis PARAMS ((bfd_vma, unsigned long, struct disassemble_info *));
+
+static void
+printop PARAMS ((struct disassemble_info *, OPSPEC *,
+                unsigned long, bfd_vma, int));
+
+static void
+init_disasm PARAMS ((void));
+
+static void
+install PARAMS ((INSTAB *instptr));
+
+/*
+*              Disassemble an M88000 Instruction
+*
+*
+*       This module decodes the instruction at memaddr.
+*
+*                      Revision History
+*
+*       Revision 1.0    11/08/85        Creation date by Motorola
+*                      05/11/89        R. Trawick adapted to GDB interface.
+*                      07/12/93        Ian Lance Taylor updated to
+*                                      binutils interface.
+*/
+
+int
+print_insn_m88k (memaddr, info)
+     bfd_vma memaddr;
+     struct disassemble_info *info;
+{
+  bfd_byte buffer[4];
+  int status;
+
+  /* Instruction addresses may have low two bits set. Clear them.      */
+  memaddr &=~ (bfd_vma) 3;
+
+  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+
+  return m88kdis (memaddr, _do_getb32 (buffer), info);
+}
+
+/*
+ * disassemble the instruction in 'instruction'.
+ * '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 disassembled instruction is written to 'info'.
+ * The function returns the length of this instruction in bytes.
+ */
+
+static int
+m88kdis (pc, instruction, info)
+     bfd_vma pc;
+     unsigned long instruction;
+     struct disassemble_info *info;
+{
+  static int ihashtab_initialized = 0;
+  unsigned int opcode;
+  INSTAB *entry_ptr;
+  int opmask;
+  int class;
+
+  if (! ihashtab_initialized)
+    init_disasm ();
+
+  /* create a the appropriate mask to isolate the opcode */
+  opmask = DEFMASK;
+  class = instruction & DEFMASK;
+  if ((class >= SFU0) && (class <= SFU7))
+    {
+      if (instruction < SFU1)
+       opmask = CTRLMASK;
+      else
+       opmask = SFUMASK;
+    }
+  else if (class == RRR)
+    opmask = RRRMASK;
+  else if (class == RRI10)
+    opmask = RRI10MASK;
+
+  /* isolate the opcode */
+  opcode = instruction & opmask;
+
+  /* search the hash table with the isolated opcode */
+  for (entry_ptr = hashtable[opcode % HASHVAL];
+       (entry_ptr != NULL) && (entry_ptr->opcode != opcode);
+       entry_ptr = entry_ptr->next)
+    ;
+
+  if (entry_ptr == NULL)
+    (*info->fprintf_func) (info->stream, "word\t%08x", instruction);
+  else
+    {
+      (*info->fprintf_func) (info->stream, "%s ", entry_ptr->mnemonic);
+      printop (info, &(entry_ptr->op1), instruction, pc, 1);
+      printop (info, &(entry_ptr->op2), instruction, pc, 0);
+      printop (info, &(entry_ptr->op3), instruction, pc, 0);
+    }
+
+  return 4;
+}
+\f
+/*
+*                      Decode an Operand of an Instruction
+*
+*                      Functional Description
+*
+*       This module formats and writes an operand of an instruction to info
+*       based on the operand specification.  When the first flag is set this
+*       is the first operand of an instruction.  Undefined operand types
+*       cause a <dis error> message.
+*
+*                      Parameters
+*      disassemble_info        where the operand may be printed
+*       OPSPEC  *opptr          Pointer to an operand specification
+*       UINT    inst            Instruction from which operand is extracted
+*      UINT    pc              PC of instruction; used for pc-relative disp.
+*       int     first           Flag which if nonzero indicates the first
+*                               operand of an instruction
+*
+*                      Output
+*
+*       The operand specified is extracted from the instruction and is
+*       written to buf in the format specified. The operand is preceded
+*       by a comma if it is not the first operand of an instruction and it
+*       is not a register indirect form.  Registers are preceded by 'r' and
+*       hex values by '0x'.
+*
+*                      Revision History
+*
+*       Revision 1.0    11/08/85        Creation date
+*/
+
+static void
+printop (info, opptr, inst, pc, first)
+     struct disassemble_info *info;
+     OPSPEC *opptr;
+     unsigned long inst;
+     bfd_vma pc;
+     int first;
+{
+  int extracted_field;
+  char *cond_mask_sym;
+
+  if (opptr->width == 0)
+    return;
+
+  if (! first)
+    {
+      switch (opptr->type)
+       {
+       case REGSC:
+       case CONT:
+         break;
+       default:
+         (*info->fprintf_func) (info->stream, ",");
+         break;
+       }
+    }
+
+  switch (opptr->type)
+    {
+    case CRREG:
+      (*info->fprintf_func) (info->stream, "cr%d",
+                            UEXT (inst, opptr->offset, opptr->width));
+      break;
+
+    case FCRREG:
+      (*info->fprintf_func) (info->stream, "fcr%d",
+                            UEXT (inst, opptr->offset, opptr->width));
+      break;
+
+    case REGSC:
+      (*info->fprintf_func) (info->stream, "[r%d]",
+                            UEXT (inst, opptr->offset, opptr->width));
+      break;
+
+    case REG:
+      (*info->fprintf_func) (info->stream, "r%d",
+                            UEXT (inst, opptr->offset, opptr->width));
+      break;
+
+    case HEX:
+      extracted_field = UEXT (inst, opptr->offset, opptr->width);
+      if (extracted_field == 0)
+       (*info->fprintf_func) (info->stream, "0");
+      else
+       (*info->fprintf_func) (info->stream, "0x%02x", extracted_field);
+      break;
+
+    case CONDMASK:
+      extracted_field = UEXT (inst, opptr->offset, opptr->width);
+      switch (extracted_field & 0x0f)
+       {
+       case 0x1: cond_mask_sym = "gt0"; break;
+       case 0x2: cond_mask_sym = "eq0"; break;
+       case 0x3: cond_mask_sym = "ge0"; break;
+       case 0xc: cond_mask_sym = "lt0"; break;
+       case 0xd: cond_mask_sym = "ne0"; break;
+       case 0xe: cond_mask_sym = "le0"; break;
+       default: cond_mask_sym = NULL; break;
+       }
+      if (cond_mask_sym != NULL)
+       (*info->fprintf_func) (info->stream, "%s", cond_mask_sym);
+      else
+       (*info->fprintf_func) (info->stream, "%x", extracted_field);
+      break;
+                       
+    case PCREL:
+      (*info->print_address_func)
+       (pc + (4 * (SEXT (inst, opptr->offset, opptr->width))),
+        info);
+      break;
+
+    case CONT:
+      (*info->fprintf_func) (info->stream, "%d,r%d",
+                            UEXT (inst, opptr->offset, 5),
+                            UEXT (inst, (opptr->offset) + 5, 5));
+      break;
+
+    case BF:
+      (*info->fprintf_func) (info->stream, "%d<%d>",
+                             UEXT (inst, (opptr->offset) + 5, 5),
+                             UEXT (inst, opptr->offset, 5));
+      break;
+
+    default:
+      (*info->fprintf_func) (info->stream, "# <dis error: %08x>", inst);
+    }
+}
+
+/*
+*                 Initialize the Disassembler Instruction Table
+*
+*       Initialize the hash table and instruction table for the disassembler.
+*       This should be called once before the first call to disasm().
+*
+*                      Parameters
+*
+*                      Output
+*
+*       If the debug option is selected, certain statistics about the hashing
+*       distribution are written to stdout.
+*
+*                      Revision History
+*
+*       Revision 1.0    11/08/85        Creation date
+*/
+
+static void
+init_disasm ()
+{
+   int i, size;
+
+   for (i = 0; i < HASHVAL; i++)
+     hashtable[i] = NULL;
+
+   size = sizeof (instructions) / sizeof (INSTAB);
+   for (i = 0; i < size; i++)
+     install (&instructions[i]);
+}
+
+/*
+*       Insert an instruction into the disassembler table by hashing the
+*       opcode and inserting it into the linked list for that hash value.
+*
+*                      Parameters
+*
+*       INSTAB *instptr         Pointer to the entry in the instruction table
+*                               to be installed
+*
+*       Revision 1.0    11/08/85        Creation date
+*                      05/11/89        R. TRAWICK ADAPTED FROM MOTOROLA
+*/
+
+static void
+install (instptr)
+     INSTAB *instptr;
+{
+  unsigned int i;
+
+  i = (instptr->opcode) % HASHVAL;
+  instptr->next = hashtable[i];
+  hashtable[i] = instptr;
+}