* m10200-dis.c (print_insn_mn10200): Recognize 'break' pseudo-op.
authorMark Alexander <marka@cygnus>
Fri, 19 Jun 1998 16:19:12 +0000 (16:19 +0000)
committerMark Alexander <marka@cygnus>
Fri, 19 Jun 1998 16:19:12 +0000 (16:19 +0000)
opcodes/ChangeLog
opcodes/m10200-dis.c [new file with mode: 0644]

index a3b76d153a4a5c41584b143bf615ad14b22e5950..debf81e0e37906af79090c9a04150d6090b18fdc 100644 (file)
@@ -1,3 +1,7 @@
+Fri Jun 19 09:16:42 1998  Mark Alexander  <marka@cygnus.com>
+
+       * m10200-dis.c (print_insn_mn10200): Recognize 'break' pseudo-op.
+
 start-sanitize-am33
 Fri Jun 19 09:42:51 1998  Jeffrey A Law  (law@cygnus.com)
 
diff --git a/opcodes/m10200-dis.c b/opcodes/m10200-dis.c
new file mode 100644 (file)
index 0000000..9572f9e
--- /dev/null
@@ -0,0 +1,340 @@
+/* Disassemble MN10200 instructions.
+   Copyright (C) 1996, 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+
+#include "ansidecl.h"
+#include "opcode/mn10200.h" 
+#include "dis-asm.h"
+#include "opintl.h"
+
+static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
+                                unsigned long insn, unsigned long,
+                                unsigned int));
+
+int 
+print_insn_mn10200 (memaddr, info)
+     bfd_vma memaddr;
+     struct disassemble_info *info;
+{
+  int status;
+  bfd_byte buffer[4];
+  unsigned long insn;
+  unsigned long extension = 0;
+  unsigned int consume;
+
+  /* First figure out how big the opcode is.  */
+  status = (*info->read_memory_func) (memaddr, buffer, 1, info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+  insn = *(unsigned char *) buffer;
+
+  /* These are one byte insns.  */
+  if ((insn & 0xf0) == 0x00
+      || (insn & 0xf0) == 0x10
+      || (insn & 0xf0) == 0x20
+      || (insn & 0xf0) == 0x30
+      || ((insn & 0xf0) == 0x80
+         && (insn & 0x0c) >> 2 != (insn & 0x03))
+      || (insn & 0xf0) == 0x90
+      || (insn & 0xf0) == 0xa0
+      || (insn & 0xf0) == 0xb0
+      || (insn & 0xff) == 0xeb
+      || (insn & 0xff) == 0xf6
+      || (insn & 0xff) == 0xfe
+      || (insn & 0xff) == 0xff)
+    {
+      extension = 0;
+      consume = 1;
+    }
+
+  /* These are two byte insns.  */
+  else if ((insn & 0xf0) == 0x40
+          || (insn & 0xf0) == 0x50
+          || (insn & 0xf0) == 0x60
+          || (insn & 0xf0) == 0x70
+          || (insn & 0xf0) == 0x80
+          || (insn & 0xfc) == 0xd0
+          || (insn & 0xfc) == 0xd4
+          || (insn & 0xfc) == 0xd8
+          || (insn & 0xfc) == 0xe0
+          || (insn & 0xfc) == 0xe4
+          || (insn & 0xff) == 0xe8
+          || (insn & 0xff) == 0xe9
+          || (insn & 0xff) == 0xea
+          || (insn & 0xff) == 0xf0
+          || (insn & 0xff) == 0xf1
+          || (insn & 0xff) == 0xf2
+          || (insn & 0xff) == 0xf3)
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+          return -1;
+       }
+      insn = bfd_getb16 (buffer);
+      consume = 2;
+    }
+
+  /* These are three byte insns with a 16bit operand in little
+     endian form.  */
+  else if ((insn & 0xf0) == 0xc0
+          || (insn & 0xfc) == 0xdc
+          || (insn & 0xfc) == 0xec
+          || (insn & 0xff) == 0xf8
+          || (insn & 0xff) == 0xf9
+          || (insn & 0xff) == 0xfa
+          || (insn & 0xff) == 0xfb
+          || (insn & 0xff) == 0xfc
+          || (insn & 0xff) == 0xfd)
+    {
+      status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn <<= 16;
+      insn |= bfd_getl16 (buffer);
+      extension = 0;
+      consume = 3;
+    }
+  /* These are three byte insns too, but we don't have to mess with
+     endianness stuff.  */
+  else if ((insn & 0xff) == 0xf5)
+    {
+      status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn <<= 16;
+      insn |= bfd_getb16 (buffer);
+      extension = 0;
+      consume = 3;
+    }
+
+  /* These are four byte insns.  */
+  else if ((insn & 0xff) == 0xf7)
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn = bfd_getb16 (buffer);
+      insn <<= 16;
+      status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn |= bfd_getl16 (buffer);
+      extension = 0;
+      consume = 4;
+    }
+
+  /* These are five byte insns.  */
+  else if ((insn & 0xff) == 0xf4)
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn = bfd_getb16 (buffer);
+      insn <<= 16;
+
+      status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn |= *(unsigned char *)buffer << 8;
+
+      status = (*info->read_memory_func) (memaddr + 3, buffer, 1, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn |= *(unsigned char *)buffer;
+
+      status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      extension = *(unsigned char *)buffer;
+      consume = 5;
+    }
+  else
+    {
+      (*info->fprintf_func) (info->stream, _("unknown\t0x%02x"), insn);
+      return 1;
+    }
+
+  disassemble (memaddr, info, insn, extension, consume);
+
+  return consume;
+}
+
+static void
+disassemble (memaddr, info, insn, extension, size)
+     bfd_vma memaddr;
+     struct disassemble_info *info;
+     unsigned long insn;
+     unsigned long extension;
+     unsigned int size;
+{
+  struct mn10200_opcode *op = (struct mn10200_opcode *)mn10200_opcodes;
+  const struct mn10200_operand *operand;
+  int match = 0;
+
+  /* Find the opcode.  */
+  while (op->name)
+    {
+      int mysize, extra_shift;
+
+      if (op->format == FMT_1)
+       mysize = 1;
+      else if (op->format == FMT_2
+              || op->format == FMT_4)
+       mysize = 2;
+      else if (op->format == FMT_3
+              || op->format == FMT_5)
+       mysize = 3;
+      else if (op->format == FMT_6)
+       mysize = 4;
+      else if (op->format == FMT_7)
+       mysize = 5;
+      else
+       abort ();
+       
+      if (op->format == FMT_2 || op->format == FMT_5)
+       extra_shift = 8;
+      else if (op->format == FMT_3
+              || op->format == FMT_6
+              || op->format == FMT_7)
+       extra_shift = 16;
+      else
+       extra_shift = 0;
+
+      if ((op->mask & insn) == op->opcode
+         && size == (unsigned int) mysize)
+       {
+         const unsigned char *opindex_ptr;
+         unsigned int nocomma;
+         int paren = 0;
+         
+         match = 1;
+         (*info->fprintf_func) (info->stream, "%s\t", op->name);
+
+         /* Now print the operands.  */
+         for (opindex_ptr = op->operands, nocomma = 1;
+              *opindex_ptr != 0;
+              opindex_ptr++)
+           {
+             unsigned long value;
+
+             operand = &mn10200_operands[*opindex_ptr];
+
+             if ((operand->flags & MN10200_OPERAND_EXTENDED) != 0)
+               {
+                 value = (insn & 0xffff) << 8;
+                 value |= extension;
+               }
+             else
+               {
+                 value = ((insn >> (operand->shift))
+                          & ((1 << operand->bits) - 1));
+               }
+
+             if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
+               value = ((long)(value << (32 - operand->bits))
+                         >> (32 - operand->bits));
+
+             if (!nocomma
+                 && (!paren
+                     || ((operand->flags & MN10200_OPERAND_PAREN) == 0)))
+               (*info->fprintf_func) (info->stream, ",");
+
+             nocomma = 0;
+               
+             if ((operand->flags & MN10200_OPERAND_DREG) != 0)
+               {
+                 value = ((insn >> (operand->shift + extra_shift))
+                          & ((1 << operand->bits) - 1));
+                 (*info->fprintf_func) (info->stream, "d%d", value);
+               }
+
+             else if ((operand->flags & MN10200_OPERAND_AREG) != 0)
+               {
+                 value = ((insn >> (operand->shift + extra_shift))
+                          & ((1 << operand->bits) - 1));
+                 (*info->fprintf_func) (info->stream, "a%d", value);
+               }
+
+             else if ((operand->flags & MN10200_OPERAND_PSW) != 0)
+               (*info->fprintf_func) (info->stream, "psw");
+
+             else if ((operand->flags & MN10200_OPERAND_MDR) != 0)
+               (*info->fprintf_func) (info->stream, "mdr");
+
+             else if ((operand->flags & MN10200_OPERAND_PAREN) != 0)
+               {
+                 if (paren)
+                   (*info->fprintf_func) (info->stream, ")");
+                 else
+                   {
+                     (*info->fprintf_func) (info->stream, "(");
+                     nocomma = 1;
+                   }
+                 paren = !paren;
+               }
+
+             else if ((operand->flags & MN10200_OPERAND_PCREL) != 0)
+               (*info->print_address_func) ((value + memaddr + mysize) & 0xffffff, info);
+
+             else if ((operand->flags & MN10200_OPERAND_MEMADDR) != 0)
+               (*info->print_address_func) (value, info);
+
+             else 
+               (*info->fprintf_func) (info->stream, "%d", value);
+           }
+         /* All done. */
+         break;
+       }
+      op++;
+    }
+
+  if (!match)
+    {
+       (*info->fprintf_func) (info->stream, _("unknown\t0x%04x"), insn);
+    }
+}