From 7b61b0945fdd8320955a04e1f53b9d4d637d25bf Mon Sep 17 00:00:00 2001
From: Mark Alexander <marka@cygnus>
Date: Fri, 19 Jun 1998 16:19:12 +0000
Subject: [PATCH] 	* m10200-dis.c (print_insn_mn10200): Recognize 'break'
 pseudo-op.

---
 opcodes/ChangeLog    |   4 +
 opcodes/m10200-dis.c | 340 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 344 insertions(+)
 create mode 100644 opcodes/m10200-dis.c

diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index a3b76d153a4..debf81e0e37 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -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
index 00000000000..9572f9ea85e
--- /dev/null
+++ b/opcodes/m10200-dis.c
@@ -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);
+    }
+}