Home | History | Annotate | Download | only in opcodes
      1 /* Disassemble MN10200 instructions.
      2    Copyright (C) 1996-2014 Free Software Foundation, Inc.
      3 
      4    This file is part of the GNU opcodes library.
      5 
      6    This library is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3, or (at your option)
      9    any later version.
     10 
     11    It is distributed in the hope that it will be useful, but WITHOUT
     12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     14    License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program; if not, write to the Free Software
     18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19    MA 02110-1301, USA.  */
     20 
     21 #include "sysdep.h"
     22 #include <stdio.h>
     23 #include "opcode/mn10200.h"
     24 #include "dis-asm.h"
     25 #include "opintl.h"
     26 
     27 static void
     28 disassemble (bfd_vma memaddr,
     29 	     struct disassemble_info *info,
     30 	     unsigned long insn,
     31 	     unsigned long extension,
     32 	     unsigned int size)
     33 {
     34   struct mn10200_opcode *op = (struct mn10200_opcode *)mn10200_opcodes;
     35   const struct mn10200_operand *operand;
     36   int match = 0;
     37 
     38   /* Find the opcode.  */
     39   while (op->name)
     40     {
     41       int mysize, extra_shift;
     42 
     43       if (op->format == FMT_1)
     44 	mysize = 1;
     45       else if (op->format == FMT_2
     46 	       || op->format == FMT_4)
     47 	mysize = 2;
     48       else if (op->format == FMT_3
     49 	       || op->format == FMT_5)
     50 	mysize = 3;
     51       else if (op->format == FMT_6)
     52 	mysize = 4;
     53       else if (op->format == FMT_7)
     54 	mysize = 5;
     55       else
     56 	abort ();
     57 
     58       if (op->format == FMT_2 || op->format == FMT_5)
     59 	extra_shift = 8;
     60       else if (op->format == FMT_3
     61 	       || op->format == FMT_6
     62 	       || op->format == FMT_7)
     63 	extra_shift = 16;
     64       else
     65 	extra_shift = 0;
     66 
     67       if ((op->mask & insn) == op->opcode
     68 	  && size == (unsigned int) mysize)
     69 	{
     70 	  const unsigned char *opindex_ptr;
     71 	  unsigned int nocomma;
     72 	  int paren = 0;
     73 
     74 	  match = 1;
     75 	  (*info->fprintf_func) (info->stream, "%s\t", op->name);
     76 
     77 	  /* Now print the operands.  */
     78 	  for (opindex_ptr = op->operands, nocomma = 1;
     79 	       *opindex_ptr != 0;
     80 	       opindex_ptr++)
     81 	    {
     82 	      unsigned long value;
     83 
     84 	      operand = &mn10200_operands[*opindex_ptr];
     85 
     86 	      if ((operand->flags & MN10200_OPERAND_EXTENDED) != 0)
     87 		{
     88 		  value = (insn & 0xffff) << 8;
     89 		  value |= extension;
     90 		}
     91 	      else
     92 		{
     93 		  value = ((insn >> (operand->shift))
     94 			   & ((1L << operand->bits) - 1L));
     95 		}
     96 
     97 	      if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
     98 		value = ((long)(value << (32 - operand->bits))
     99 			  >> (32 - operand->bits));
    100 
    101 	      if (!nocomma
    102 		  && (!paren
    103 		      || ((operand->flags & MN10200_OPERAND_PAREN) == 0)))
    104 		(*info->fprintf_func) (info->stream, ",");
    105 
    106 	      nocomma = 0;
    107 
    108 	      if ((operand->flags & MN10200_OPERAND_DREG) != 0)
    109 		{
    110 		  value = ((insn >> (operand->shift + extra_shift))
    111 			   & ((1 << operand->bits) - 1));
    112 		  (*info->fprintf_func) (info->stream, "d%ld", value);
    113 		}
    114 
    115 	      else if ((operand->flags & MN10200_OPERAND_AREG) != 0)
    116 		{
    117 		  value = ((insn >> (operand->shift + extra_shift))
    118 			   & ((1 << operand->bits) - 1));
    119 		  (*info->fprintf_func) (info->stream, "a%ld", value);
    120 		}
    121 
    122 	      else if ((operand->flags & MN10200_OPERAND_PSW) != 0)
    123 		(*info->fprintf_func) (info->stream, "psw");
    124 
    125 	      else if ((operand->flags & MN10200_OPERAND_MDR) != 0)
    126 		(*info->fprintf_func) (info->stream, "mdr");
    127 
    128 	      else if ((operand->flags & MN10200_OPERAND_PAREN) != 0)
    129 		{
    130 		  if (paren)
    131 		    (*info->fprintf_func) (info->stream, ")");
    132 		  else
    133 		    {
    134 		      (*info->fprintf_func) (info->stream, "(");
    135 		      nocomma = 1;
    136 		    }
    137 		  paren = !paren;
    138 		}
    139 
    140 	      else if ((operand->flags & MN10200_OPERAND_PCREL) != 0)
    141 		(*info->print_address_func)
    142 		  ((value + memaddr + mysize) & 0xffffff, info);
    143 
    144 	      else if ((operand->flags & MN10200_OPERAND_MEMADDR) != 0)
    145 		(*info->print_address_func) (value, info);
    146 
    147 	      else
    148 		(*info->fprintf_func) (info->stream, "%ld", value);
    149 	    }
    150 	  /* All done. */
    151 	  break;
    152 	}
    153       op++;
    154     }
    155 
    156   if (!match)
    157     (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
    158 }
    159 
    160 int
    161 print_insn_mn10200 (bfd_vma memaddr, struct disassemble_info *info)
    162 {
    163   int status;
    164   bfd_byte buffer[4];
    165   unsigned long insn;
    166   unsigned long extension = 0;
    167   unsigned int consume;
    168 
    169   /* First figure out how big the opcode is.  */
    170   status = (*info->read_memory_func) (memaddr, buffer, 1, info);
    171   if (status != 0)
    172     {
    173       (*info->memory_error_func) (status, memaddr, info);
    174       return -1;
    175     }
    176 
    177   insn = *(unsigned char *) buffer;
    178 
    179   /* These are one byte insns.  */
    180   if ((insn & 0xf0) == 0x00
    181       || (insn & 0xf0) == 0x10
    182       || (insn & 0xf0) == 0x20
    183       || (insn & 0xf0) == 0x30
    184       || ((insn & 0xf0) == 0x80
    185 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
    186       || (insn & 0xf0) == 0x90
    187       || (insn & 0xf0) == 0xa0
    188       || (insn & 0xf0) == 0xb0
    189       || (insn & 0xff) == 0xeb
    190       || (insn & 0xff) == 0xf6
    191       || (insn & 0xff) == 0xfe
    192       || (insn & 0xff) == 0xff)
    193     {
    194       extension = 0;
    195       consume = 1;
    196     }
    197 
    198   /* These are two byte insns.  */
    199   else if ((insn & 0xf0) == 0x40
    200 	   || (insn & 0xf0) == 0x50
    201 	   || (insn & 0xf0) == 0x60
    202 	   || (insn & 0xf0) == 0x70
    203 	   || (insn & 0xf0) == 0x80
    204 	   || (insn & 0xfc) == 0xd0
    205 	   || (insn & 0xfc) == 0xd4
    206 	   || (insn & 0xfc) == 0xd8
    207 	   || (insn & 0xfc) == 0xe0
    208 	   || (insn & 0xfc) == 0xe4
    209 	   || (insn & 0xff) == 0xe8
    210 	   || (insn & 0xff) == 0xe9
    211 	   || (insn & 0xff) == 0xea
    212 	   || (insn & 0xff) == 0xf0
    213 	   || (insn & 0xff) == 0xf1
    214 	   || (insn & 0xff) == 0xf2
    215 	   || (insn & 0xff) == 0xf3)
    216     {
    217       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
    218       if (status != 0)
    219 	{
    220 	  (*info->memory_error_func) (status, memaddr, info);
    221 	   return -1;
    222 	}
    223       insn = bfd_getb16 (buffer);
    224       consume = 2;
    225     }
    226 
    227   /* These are three byte insns with a 16bit operand in little
    228      endian form.  */
    229   else if ((insn & 0xf0) == 0xc0
    230 	   || (insn & 0xfc) == 0xdc
    231 	   || (insn & 0xfc) == 0xec
    232 	   || (insn & 0xff) == 0xf8
    233 	   || (insn & 0xff) == 0xf9
    234 	   || (insn & 0xff) == 0xfa
    235 	   || (insn & 0xff) == 0xfb
    236 	   || (insn & 0xff) == 0xfc
    237 	   || (insn & 0xff) == 0xfd)
    238     {
    239       status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
    240       if (status != 0)
    241 	{
    242 	  (*info->memory_error_func) (status, memaddr, info);
    243 	  return -1;
    244 	}
    245       insn <<= 16;
    246       insn |= bfd_getl16 (buffer);
    247       extension = 0;
    248       consume = 3;
    249     }
    250   /* These are three byte insns too, but we don't have to mess with
    251      endianness stuff.  */
    252   else if ((insn & 0xff) == 0xf5)
    253     {
    254       status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
    255       if (status != 0)
    256 	{
    257 	  (*info->memory_error_func) (status, memaddr, info);
    258 	  return -1;
    259 	}
    260       insn <<= 16;
    261       insn |= bfd_getb16 (buffer);
    262       extension = 0;
    263       consume = 3;
    264     }
    265 
    266   /* These are four byte insns.  */
    267   else if ((insn & 0xff) == 0xf7)
    268     {
    269       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
    270       if (status != 0)
    271 	{
    272 	  (*info->memory_error_func) (status, memaddr, info);
    273 	  return -1;
    274 	}
    275       insn = bfd_getb16 (buffer);
    276       insn <<= 16;
    277       status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
    278       if (status != 0)
    279 	{
    280 	  (*info->memory_error_func) (status, memaddr, info);
    281 	  return -1;
    282 	}
    283       insn |= bfd_getl16 (buffer);
    284       extension = 0;
    285       consume = 4;
    286     }
    287 
    288   /* These are five byte insns.  */
    289   else if ((insn & 0xff) == 0xf4)
    290     {
    291       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
    292       if (status != 0)
    293 	{
    294 	  (*info->memory_error_func) (status, memaddr, info);
    295 	  return -1;
    296 	}
    297       insn = bfd_getb16 (buffer);
    298       insn <<= 16;
    299 
    300       status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
    301       if (status != 0)
    302 	{
    303 	  (*info->memory_error_func) (status, memaddr, info);
    304 	  return -1;
    305 	}
    306       insn |= (*(unsigned char *)buffer << 8) & 0xff00;
    307 
    308       status = (*info->read_memory_func) (memaddr + 3, buffer, 1, info);
    309       if (status != 0)
    310 	{
    311 	  (*info->memory_error_func) (status, memaddr, info);
    312 	  return -1;
    313 	}
    314       insn |= (*(unsigned char *)buffer) & 0xff;
    315 
    316       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
    317       if (status != 0)
    318 	{
    319 	  (*info->memory_error_func) (status, memaddr, info);
    320 	  return -1;
    321 	}
    322       extension = (*(unsigned char *)buffer) & 0xff;
    323       consume = 5;
    324     }
    325   else
    326     {
    327       (*info->fprintf_func) (info->stream, _("unknown\t0x%02lx"), insn);
    328       return 1;
    329     }
    330 
    331   disassemble (memaddr, info, insn, extension, consume);
    332 
    333   return consume;
    334 }
    335