Home | History | Annotate | Line # | Download | only in opcodes
m10300-dis.c revision 1.1.1.1
      1  1.1  christos /* Disassemble MN10300 instructions.
      2  1.1  christos    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005, 2007, 2012
      3  1.1  christos    Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This file is part of the GNU opcodes library.
      6  1.1  christos 
      7  1.1  christos    This library is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     10  1.1  christos    any later version.
     11  1.1  christos 
     12  1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     13  1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14  1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15  1.1  christos    License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with this program; if not, write to the Free Software
     19  1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20  1.1  christos    MA 02110-1301, USA.  */
     21  1.1  christos 
     22  1.1  christos #include "sysdep.h"
     23  1.1  christos #include <stdio.h>
     24  1.1  christos #include "opcode/mn10300.h"
     25  1.1  christos #include "dis-asm.h"
     26  1.1  christos #include "opintl.h"
     27  1.1  christos 
     28  1.1  christos #define HAVE_AM33_2 (info->mach == AM33_2)
     29  1.1  christos #define HAVE_AM33   (info->mach == AM33 || HAVE_AM33_2)
     30  1.1  christos #define HAVE_AM30   (info->mach == AM30)
     31  1.1  christos 
     32  1.1  christos static void
     33  1.1  christos disassemble (bfd_vma memaddr,
     34  1.1  christos 	     struct disassemble_info *info,
     35  1.1  christos 	     unsigned long insn,
     36  1.1  christos 	     unsigned int size)
     37  1.1  christos {
     38  1.1  christos   struct mn10300_opcode *op = (struct mn10300_opcode *) mn10300_opcodes;
     39  1.1  christos   const struct mn10300_operand *operand;
     40  1.1  christos   bfd_byte buffer[4];
     41  1.1  christos   unsigned long extension = 0;
     42  1.1  christos   int status, match = 0;
     43  1.1  christos 
     44  1.1  christos   /* Find the opcode.  */
     45  1.1  christos   while (op->name)
     46  1.1  christos     {
     47  1.1  christos       int mysize, extra_shift;
     48  1.1  christos 
     49  1.1  christos       if (op->format == FMT_S0)
     50  1.1  christos 	mysize = 1;
     51  1.1  christos       else if (op->format == FMT_S1
     52  1.1  christos 	       || op->format == FMT_D0)
     53  1.1  christos 	mysize = 2;
     54  1.1  christos       else if (op->format == FMT_S2
     55  1.1  christos 	       || op->format == FMT_D1)
     56  1.1  christos 	mysize = 3;
     57  1.1  christos       else if (op->format == FMT_S4)
     58  1.1  christos 	mysize = 5;
     59  1.1  christos       else if (op->format == FMT_D2)
     60  1.1  christos 	mysize = 4;
     61  1.1  christos       else if (op->format == FMT_D3)
     62  1.1  christos 	mysize = 5;
     63  1.1  christos       else if (op->format == FMT_D4)
     64  1.1  christos 	mysize = 6;
     65  1.1  christos       else if (op->format == FMT_D6)
     66  1.1  christos 	mysize = 3;
     67  1.1  christos       else if (op->format == FMT_D7 || op->format == FMT_D10)
     68  1.1  christos 	mysize = 4;
     69  1.1  christos       else if (op->format == FMT_D8)
     70  1.1  christos 	mysize = 6;
     71  1.1  christos       else if (op->format == FMT_D9)
     72  1.1  christos 	mysize = 7;
     73  1.1  christos       else
     74  1.1  christos 	mysize = 7;
     75  1.1  christos 
     76  1.1  christos       if ((op->mask & insn) == op->opcode
     77  1.1  christos 	  && size == (unsigned int) mysize
     78  1.1  christos 	  && (op->machine == 0
     79  1.1  christos 	      || (op->machine == AM33_2 && HAVE_AM33_2)
     80  1.1  christos 	      || (op->machine == AM33 && HAVE_AM33)
     81  1.1  christos 	      || (op->machine == AM30 && HAVE_AM30)))
     82  1.1  christos 	{
     83  1.1  christos 	  const unsigned char *opindex_ptr;
     84  1.1  christos 	  unsigned int nocomma;
     85  1.1  christos 	  int paren = 0;
     86  1.1  christos 
     87  1.1  christos 	  if (op->format == FMT_D1 || op->format == FMT_S1)
     88  1.1  christos 	    extra_shift = 8;
     89  1.1  christos 	  else if (op->format == FMT_D2 || op->format == FMT_D4
     90  1.1  christos 		   || op->format == FMT_S2 || op->format == FMT_S4
     91  1.1  christos 		   || op->format == FMT_S6 || op->format == FMT_D5)
     92  1.1  christos 	    extra_shift = 16;
     93  1.1  christos 	  else if (op->format == FMT_D7
     94  1.1  christos 		   || op->format == FMT_D8
     95  1.1  christos 		   || op->format == FMT_D9)
     96  1.1  christos 	    extra_shift = 8;
     97  1.1  christos 	  else
     98  1.1  christos 	    extra_shift = 0;
     99  1.1  christos 
    100  1.1  christos 	  if (size == 1 || size == 2)
    101  1.1  christos 	    extension = 0;
    102  1.1  christos 
    103  1.1  christos 	  else if (size == 3
    104  1.1  christos 		   && (op->format == FMT_D1
    105  1.1  christos 		       || op->opcode == 0xdf0000
    106  1.1  christos 		       || op->opcode == 0xde0000))
    107  1.1  christos 	    extension = 0;
    108  1.1  christos 
    109  1.1  christos 	  else if (size == 3
    110  1.1  christos 		   && op->format == FMT_D6)
    111  1.1  christos 	    extension = 0;
    112  1.1  christos 
    113  1.1  christos 	  else if (size == 3)
    114  1.1  christos 	    {
    115  1.1  christos 	      insn &= 0xff0000;
    116  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
    117  1.1  christos 	      if (status != 0)
    118  1.1  christos 		{
    119  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    120  1.1  christos 		  return;
    121  1.1  christos 		}
    122  1.1  christos 
    123  1.1  christos 	      insn |= bfd_getl16 (buffer);
    124  1.1  christos 	      extension = 0;
    125  1.1  christos 	    }
    126  1.1  christos 	  else if (size == 4
    127  1.1  christos 		   && (op->opcode == 0xfaf80000
    128  1.1  christos 		       || op->opcode == 0xfaf00000
    129  1.1  christos 		       || op->opcode == 0xfaf40000))
    130  1.1  christos 	    extension = 0;
    131  1.1  christos 
    132  1.1  christos 	  else if (size == 4
    133  1.1  christos 		   && (op->format == FMT_D7
    134  1.1  christos 		       || op->format == FMT_D10))
    135  1.1  christos 	    extension = 0;
    136  1.1  christos 
    137  1.1  christos 	  else if (size == 4)
    138  1.1  christos 	    {
    139  1.1  christos 	      insn &= 0xffff0000;
    140  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
    141  1.1  christos 	      if (status != 0)
    142  1.1  christos 		{
    143  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    144  1.1  christos 		  return;
    145  1.1  christos 		}
    146  1.1  christos 
    147  1.1  christos 	      insn |= bfd_getl16 (buffer);
    148  1.1  christos 	      extension = 0;
    149  1.1  christos 	    }
    150  1.1  christos 	  else if (size == 5 && op->opcode == 0xdc000000)
    151  1.1  christos 	    {
    152  1.1  christos 	      unsigned long temp = 0;
    153  1.1  christos 
    154  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
    155  1.1  christos 	      if (status != 0)
    156  1.1  christos 		{
    157  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    158  1.1  christos 		  return;
    159  1.1  christos 		}
    160  1.1  christos 	      temp |= bfd_getl32 (buffer);
    161  1.1  christos 
    162  1.1  christos 	      insn &= 0xff000000;
    163  1.1  christos 	      insn |= (temp & 0xffffff00) >> 8;
    164  1.1  christos 	      extension = temp & 0xff;
    165  1.1  christos 	    }
    166  1.1  christos 	  else if (size == 5 && op->format == FMT_D3)
    167  1.1  christos 	    {
    168  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
    169  1.1  christos 	      if (status != 0)
    170  1.1  christos 		{
    171  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    172  1.1  christos 		  return;
    173  1.1  christos 		}
    174  1.1  christos 	      insn &= 0xffff0000;
    175  1.1  christos 	      insn |= bfd_getl16 (buffer);
    176  1.1  christos 
    177  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
    178  1.1  christos 	      if (status != 0)
    179  1.1  christos 		{
    180  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    181  1.1  christos 		  return;
    182  1.1  christos 		}
    183  1.1  christos 	      extension = *(unsigned char *) buffer;
    184  1.1  christos 	    }
    185  1.1  christos 	  else if (size == 5)
    186  1.1  christos 	    {
    187  1.1  christos 	      unsigned long temp = 0;
    188  1.1  christos 
    189  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
    190  1.1  christos 	      if (status != 0)
    191  1.1  christos 		{
    192  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    193  1.1  christos 		  return;
    194  1.1  christos 		}
    195  1.1  christos 	      temp |= bfd_getl16 (buffer);
    196  1.1  christos 
    197  1.1  christos 	      insn &= 0xff0000ff;
    198  1.1  christos 	      insn |= temp << 8;
    199  1.1  christos 
    200  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
    201  1.1  christos 	      if (status != 0)
    202  1.1  christos 		{
    203  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    204  1.1  christos 		  return;
    205  1.1  christos 		}
    206  1.1  christos 	      extension = *(unsigned char *) buffer;
    207  1.1  christos 	    }
    208  1.1  christos 	  else if (size == 6 && op->format == FMT_D8)
    209  1.1  christos 	    {
    210  1.1  christos 	      insn &= 0xffffff00;
    211  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
    212  1.1  christos 	      if (status != 0)
    213  1.1  christos 		{
    214  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    215  1.1  christos 		  return;
    216  1.1  christos 		}
    217  1.1  christos 	      insn |= *(unsigned char *) buffer;
    218  1.1  christos 
    219  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
    220  1.1  christos 	      if (status != 0)
    221  1.1  christos 		{
    222  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    223  1.1  christos 		  return;
    224  1.1  christos 		}
    225  1.1  christos 	      extension = bfd_getl16 (buffer);
    226  1.1  christos 	    }
    227  1.1  christos 	  else if (size == 6)
    228  1.1  christos 	    {
    229  1.1  christos 	      unsigned long temp = 0;
    230  1.1  christos 
    231  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
    232  1.1  christos 	      if (status != 0)
    233  1.1  christos 		{
    234  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    235  1.1  christos 		  return;
    236  1.1  christos 		}
    237  1.1  christos 	      temp |= bfd_getl32 (buffer);
    238  1.1  christos 
    239  1.1  christos 	      insn &= 0xffff0000;
    240  1.1  christos 	      insn |= (temp >> 16) & 0xffff;
    241  1.1  christos 	      extension = temp & 0xffff;
    242  1.1  christos 	    }
    243  1.1  christos 	  else if (size == 7 && op->format == FMT_D9)
    244  1.1  christos 	    {
    245  1.1  christos 	      insn &= 0xffffff00;
    246  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
    247  1.1  christos 	      if (status != 0)
    248  1.1  christos 		{
    249  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    250  1.1  christos 		  return;
    251  1.1  christos 		}
    252  1.1  christos 	      extension = bfd_getl32 (buffer);
    253  1.1  christos 	      insn |= (extension & 0xff000000) >> 24;
    254  1.1  christos 	      extension &= 0xffffff;
    255  1.1  christos 	    }
    256  1.1  christos 	  else if (size == 7 && op->opcode == 0xdd000000)
    257  1.1  christos 	    {
    258  1.1  christos 	      unsigned long temp = 0;
    259  1.1  christos 
    260  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
    261  1.1  christos 	      if (status != 0)
    262  1.1  christos 		{
    263  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    264  1.1  christos 		  return;
    265  1.1  christos 		}
    266  1.1  christos 	      temp |= bfd_getl32 (buffer);
    267  1.1  christos 
    268  1.1  christos 	      insn &= 0xff000000;
    269  1.1  christos 	      insn |= (temp >> 8) & 0xffffff;
    270  1.1  christos 	      extension = (temp & 0xff) << 16;
    271  1.1  christos 
    272  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
    273  1.1  christos 	      if (status != 0)
    274  1.1  christos 		{
    275  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    276  1.1  christos 		  return;
    277  1.1  christos 		}
    278  1.1  christos 	      extension |= bfd_getb16 (buffer);
    279  1.1  christos 	    }
    280  1.1  christos 	  else if (size == 7)
    281  1.1  christos 	    {
    282  1.1  christos 	      unsigned long temp = 0;
    283  1.1  christos 
    284  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
    285  1.1  christos 	      if (status != 0)
    286  1.1  christos 		{
    287  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    288  1.1  christos 		  return;
    289  1.1  christos 		}
    290  1.1  christos 	      temp |= bfd_getl32 (buffer);
    291  1.1  christos 
    292  1.1  christos 	      insn &= 0xffff0000;
    293  1.1  christos 	      insn |= (temp >> 16) & 0xffff;
    294  1.1  christos 	      extension = (temp & 0xffff) << 8;
    295  1.1  christos 
    296  1.1  christos 	      status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
    297  1.1  christos 	      if (status != 0)
    298  1.1  christos 		{
    299  1.1  christos 		  (*info->memory_error_func) (status, memaddr, info);
    300  1.1  christos 		  return;
    301  1.1  christos 		}
    302  1.1  christos 	      extension |= *(unsigned char *) buffer;
    303  1.1  christos 	    }
    304  1.1  christos 
    305  1.1  christos 	  match = 1;
    306  1.1  christos 	  (*info->fprintf_func) (info->stream, "%s\t", op->name);
    307  1.1  christos 
    308  1.1  christos 	  /* Now print the operands.  */
    309  1.1  christos 	  for (opindex_ptr = op->operands, nocomma = 1;
    310  1.1  christos 	       *opindex_ptr != 0;
    311  1.1  christos 	       opindex_ptr++)
    312  1.1  christos 	    {
    313  1.1  christos 	      unsigned long value;
    314  1.1  christos 
    315  1.1  christos 	      operand = &mn10300_operands[*opindex_ptr];
    316  1.1  christos 
    317  1.1  christos 	      /* If this operand is a PLUS (autoincrement), then do not emit
    318  1.1  christos 		 a comma before emitting the plus.  */
    319  1.1  christos 	      if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
    320  1.1  christos 		nocomma = 1;
    321  1.1  christos 
    322  1.1  christos 	      if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
    323  1.1  christos 		{
    324  1.1  christos 		  unsigned long temp;
    325  1.1  christos 
    326  1.1  christos 		  value = insn & ((1 << operand->bits) - 1);
    327  1.1  christos 		  value <<= (32 - operand->bits);
    328  1.1  christos 		  temp = extension >> operand->shift;
    329  1.1  christos 		  temp &= ((1 << (32 - operand->bits)) - 1);
    330  1.1  christos 		  value |= temp;
    331  1.1  christos 		  value = ((value ^ (((unsigned long) 1) << 31))
    332  1.1  christos 			   - (((unsigned long) 1) << 31));
    333  1.1  christos 		}
    334  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
    335  1.1  christos 		{
    336  1.1  christos 		  unsigned long temp;
    337  1.1  christos 
    338  1.1  christos 		  value = insn & ((1 << operand->bits) - 1);
    339  1.1  christos 		  value <<= (24 - operand->bits);
    340  1.1  christos 		  temp = extension >> operand->shift;
    341  1.1  christos 		  temp &= ((1 << (24 - operand->bits)) - 1);
    342  1.1  christos 		  value |= temp;
    343  1.1  christos 		  if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
    344  1.1  christos 		    value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
    345  1.1  christos 		}
    346  1.1  christos 	      else if ((operand->flags & (MN10300_OPERAND_FSREG
    347  1.1  christos 					  | MN10300_OPERAND_FDREG)))
    348  1.1  christos 		{
    349  1.1  christos 		  /* See m10300-opc.c just before #define FSM0 for an
    350  1.1  christos 		     explanation of these variables.  Note that
    351  1.1  christos 		     FMT-implied shifts are not taken into account for
    352  1.1  christos 		     FP registers.  */
    353  1.1  christos 		  unsigned long mask_low, mask_high;
    354  1.1  christos 		  int shl_low, shr_high, shl_high;
    355  1.1  christos 
    356  1.1  christos 		  switch (operand->bits)
    357  1.1  christos 		    {
    358  1.1  christos 		    case 5:
    359  1.1  christos 		      /* Handle regular FP registers.  */
    360  1.1  christos 		      if (operand->shift >= 0)
    361  1.1  christos 			{
    362  1.1  christos 			  /* This is an `m' register.  */
    363  1.1  christos 			  shl_low = operand->shift;
    364  1.1  christos 			  shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
    365  1.1  christos 			}
    366  1.1  christos 		      else
    367  1.1  christos 			{
    368  1.1  christos 			  /* This is an `n' register.  */
    369  1.1  christos 			  shl_low = -operand->shift;
    370  1.1  christos 			  shl_high = shl_low / 4;
    371  1.1  christos 			}
    372  1.1  christos 		      mask_low = 0x0f;
    373  1.1  christos 		      mask_high = 0x10;
    374  1.1  christos 		      shr_high = 4;
    375  1.1  christos 		      break;
    376  1.1  christos 
    377  1.1  christos 		    case 3:
    378  1.1  christos 		      /* Handle accumulators.  */
    379  1.1  christos 		      shl_low = -operand->shift;
    380  1.1  christos 		      shl_high = 0;
    381  1.1  christos 		      mask_low = 0x03;
    382  1.1  christos 		      mask_high = 0x04;
    383  1.1  christos 		      shr_high = 2;
    384  1.1  christos 		      break;
    385  1.1  christos 
    386  1.1  christos 		    default:
    387  1.1  christos 		      abort ();
    388  1.1  christos 		    }
    389  1.1  christos 		  value = ((((insn >> shl_high) << shr_high) & mask_high)
    390  1.1  christos 			   | ((insn >> shl_low) & mask_low));
    391  1.1  christos 		}
    392  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
    393  1.1  christos 		value = ((extension >> (operand->shift))
    394  1.1  christos 			 & ((1 << operand->bits) - 1));
    395  1.1  christos 
    396  1.1  christos 	      else
    397  1.1  christos 		value = ((insn >> (operand->shift))
    398  1.1  christos 			 & ((1 << operand->bits) - 1));
    399  1.1  christos 
    400  1.1  christos 	      if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
    401  1.1  christos 		  /* These are properly extended by the code above.  */
    402  1.1  christos 		  && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
    403  1.1  christos 		value = ((value ^ (((unsigned long) 1) << (operand->bits - 1)))
    404  1.1  christos 			 - (((unsigned long) 1) << (operand->bits - 1)));
    405  1.1  christos 
    406  1.1  christos 	      if (!nocomma
    407  1.1  christos 		  && (!paren
    408  1.1  christos 		      || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
    409  1.1  christos 		(*info->fprintf_func) (info->stream, ",");
    410  1.1  christos 
    411  1.1  christos 	      nocomma = 0;
    412  1.1  christos 
    413  1.1  christos 	      if ((operand->flags & MN10300_OPERAND_DREG) != 0)
    414  1.1  christos 		{
    415  1.1  christos 		  value = ((insn >> (operand->shift + extra_shift))
    416  1.1  christos 			   & ((1 << operand->bits) - 1));
    417  1.1  christos 		  (*info->fprintf_func) (info->stream, "d%d", (int) value);
    418  1.1  christos 		}
    419  1.1  christos 
    420  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
    421  1.1  christos 		{
    422  1.1  christos 		  value = ((insn >> (operand->shift + extra_shift))
    423  1.1  christos 			   & ((1 << operand->bits) - 1));
    424  1.1  christos 		  (*info->fprintf_func) (info->stream, "a%d", (int) value);
    425  1.1  christos 		}
    426  1.1  christos 
    427  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_SP) != 0)
    428  1.1  christos 		(*info->fprintf_func) (info->stream, "sp");
    429  1.1  christos 
    430  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
    431  1.1  christos 		(*info->fprintf_func) (info->stream, "psw");
    432  1.1  christos 
    433  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
    434  1.1  christos 		(*info->fprintf_func) (info->stream, "mdr");
    435  1.1  christos 
    436  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
    437  1.1  christos 		{
    438  1.1  christos 		  value = ((insn >> (operand->shift + extra_shift))
    439  1.1  christos 			   & ((1 << operand->bits) - 1));
    440  1.1  christos 		  if (value < 8)
    441  1.1  christos 		    (*info->fprintf_func) (info->stream, "r%d", (int) value);
    442  1.1  christos 		  else if (value < 12)
    443  1.1  christos 		    (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
    444  1.1  christos 		  else
    445  1.1  christos 		    (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
    446  1.1  christos 		}
    447  1.1  christos 
    448  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
    449  1.1  christos 		{
    450  1.1  christos 		  value = ((insn >> (operand->shift + extra_shift))
    451  1.1  christos 			   & ((1 << operand->bits) - 1));
    452  1.1  christos 		  if (value == 0)
    453  1.1  christos 		    (*info->fprintf_func) (info->stream, "sp");
    454  1.1  christos 		  else
    455  1.1  christos 		    (*info->fprintf_func) (info->stream, "xr%d", (int) value);
    456  1.1  christos 		}
    457  1.1  christos 
    458  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_FSREG) != 0)
    459  1.1  christos 		(*info->fprintf_func) (info->stream, "fs%d", (int) value);
    460  1.1  christos 
    461  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_FDREG) != 0)
    462  1.1  christos 		(*info->fprintf_func) (info->stream, "fd%d", (int) value);
    463  1.1  christos 
    464  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_FPCR) != 0)
    465  1.1  christos 		(*info->fprintf_func) (info->stream, "fpcr");
    466  1.1  christos 
    467  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_USP) != 0)
    468  1.1  christos 		(*info->fprintf_func) (info->stream, "usp");
    469  1.1  christos 
    470  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
    471  1.1  christos 		(*info->fprintf_func) (info->stream, "ssp");
    472  1.1  christos 
    473  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
    474  1.1  christos 		(*info->fprintf_func) (info->stream, "msp");
    475  1.1  christos 
    476  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_PC) != 0)
    477  1.1  christos 		(*info->fprintf_func) (info->stream, "pc");
    478  1.1  christos 
    479  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
    480  1.1  christos 		(*info->fprintf_func) (info->stream, "epsw");
    481  1.1  christos 
    482  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
    483  1.1  christos 		(*info->fprintf_func) (info->stream, "+");
    484  1.1  christos 
    485  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
    486  1.1  christos 		{
    487  1.1  christos 		  if (paren)
    488  1.1  christos 		    (*info->fprintf_func) (info->stream, ")");
    489  1.1  christos 		  else
    490  1.1  christos 		    {
    491  1.1  christos 		      (*info->fprintf_func) (info->stream, "(");
    492  1.1  christos 		      nocomma = 1;
    493  1.1  christos 		    }
    494  1.1  christos 		  paren = !paren;
    495  1.1  christos 		}
    496  1.1  christos 
    497  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
    498  1.1  christos 		(*info->print_address_func) ((long) value + memaddr, info);
    499  1.1  christos 
    500  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
    501  1.1  christos 		(*info->print_address_func) (value, info);
    502  1.1  christos 
    503  1.1  christos 	      else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
    504  1.1  christos 		{
    505  1.1  christos 		  int comma = 0;
    506  1.1  christos 
    507  1.1  christos 		  (*info->fprintf_func) (info->stream, "[");
    508  1.1  christos 		  if (value & 0x80)
    509  1.1  christos 		    {
    510  1.1  christos 		      (*info->fprintf_func) (info->stream, "d2");
    511  1.1  christos 		      comma = 1;
    512  1.1  christos 		    }
    513  1.1  christos 
    514  1.1  christos 		  if (value & 0x40)
    515  1.1  christos 		    {
    516  1.1  christos 		      if (comma)
    517  1.1  christos 			(*info->fprintf_func) (info->stream, ",");
    518  1.1  christos 		      (*info->fprintf_func) (info->stream, "d3");
    519  1.1  christos 		      comma = 1;
    520  1.1  christos 		    }
    521  1.1  christos 
    522  1.1  christos 		  if (value & 0x20)
    523  1.1  christos 		    {
    524  1.1  christos 		      if (comma)
    525  1.1  christos 			(*info->fprintf_func) (info->stream, ",");
    526  1.1  christos 		      (*info->fprintf_func) (info->stream, "a2");
    527  1.1  christos 		      comma = 1;
    528  1.1  christos 		    }
    529  1.1  christos 
    530  1.1  christos 		  if (value & 0x10)
    531  1.1  christos 		    {
    532  1.1  christos 		      if (comma)
    533  1.1  christos 			(*info->fprintf_func) (info->stream, ",");
    534  1.1  christos 		      (*info->fprintf_func) (info->stream, "a3");
    535  1.1  christos 		      comma = 1;
    536  1.1  christos 		    }
    537  1.1  christos 
    538  1.1  christos 		  if (value & 0x08)
    539  1.1  christos 		    {
    540  1.1  christos 		      if (comma)
    541  1.1  christos 			(*info->fprintf_func) (info->stream, ",");
    542  1.1  christos 		      (*info->fprintf_func) (info->stream, "other");
    543  1.1  christos 		      comma = 1;
    544  1.1  christos 		    }
    545  1.1  christos 
    546  1.1  christos 		  if (value & 0x04)
    547  1.1  christos 		    {
    548  1.1  christos 		      if (comma)
    549  1.1  christos 			(*info->fprintf_func) (info->stream, ",");
    550  1.1  christos 		      (*info->fprintf_func) (info->stream, "exreg0");
    551  1.1  christos 		      comma = 1;
    552  1.1  christos 		    }
    553  1.1  christos 		  if (value & 0x02)
    554  1.1  christos 		    {
    555  1.1  christos 		      if (comma)
    556  1.1  christos 			(*info->fprintf_func) (info->stream, ",");
    557  1.1  christos 		      (*info->fprintf_func) (info->stream, "exreg1");
    558  1.1  christos 		      comma = 1;
    559  1.1  christos 		    }
    560  1.1  christos 		  if (value & 0x01)
    561  1.1  christos 		    {
    562  1.1  christos 		      if (comma)
    563  1.1  christos 			(*info->fprintf_func) (info->stream, ",");
    564  1.1  christos 		      (*info->fprintf_func) (info->stream, "exother");
    565  1.1  christos 		      comma = 1;
    566  1.1  christos 		    }
    567  1.1  christos 		  (*info->fprintf_func) (info->stream, "]");
    568  1.1  christos 		}
    569  1.1  christos 
    570  1.1  christos 	      else
    571  1.1  christos 		(*info->fprintf_func) (info->stream, "%ld", (long) value);
    572  1.1  christos 	    }
    573  1.1  christos 	  /* All done. */
    574  1.1  christos 	  break;
    575  1.1  christos 	}
    576  1.1  christos       op++;
    577  1.1  christos     }
    578  1.1  christos 
    579  1.1  christos   if (!match)
    580  1.1  christos     /* xgettext:c-format */
    581  1.1  christos     (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
    582  1.1  christos }
    583  1.1  christos 
    584  1.1  christos int
    585  1.1  christos print_insn_mn10300 (bfd_vma memaddr, struct disassemble_info *info)
    586  1.1  christos {
    587  1.1  christos   int status;
    588  1.1  christos   bfd_byte buffer[4];
    589  1.1  christos   unsigned long insn;
    590  1.1  christos   unsigned int consume;
    591  1.1  christos 
    592  1.1  christos   /* First figure out how big the opcode is.  */
    593  1.1  christos   status = (*info->read_memory_func) (memaddr, buffer, 1, info);
    594  1.1  christos   if (status != 0)
    595  1.1  christos     {
    596  1.1  christos       (*info->memory_error_func) (status, memaddr, info);
    597  1.1  christos       return -1;
    598  1.1  christos     }
    599  1.1  christos   insn = *(unsigned char *) buffer;
    600  1.1  christos 
    601  1.1  christos   /* These are one byte insns.  */
    602  1.1  christos   if ((insn & 0xf3) == 0x00
    603  1.1  christos       || (insn & 0xf0) == 0x10
    604  1.1  christos       || (insn & 0xfc) == 0x3c
    605  1.1  christos       || (insn & 0xf3) == 0x41
    606  1.1  christos       || (insn & 0xf3) == 0x40
    607  1.1  christos       || (insn & 0xfc) == 0x50
    608  1.1  christos       || (insn & 0xfc) == 0x54
    609  1.1  christos       || (insn & 0xf0) == 0x60
    610  1.1  christos       || (insn & 0xf0) == 0x70
    611  1.1  christos       || ((insn & 0xf0) == 0x80
    612  1.1  christos 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
    613  1.1  christos       || ((insn & 0xf0) == 0x90
    614  1.1  christos 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
    615  1.1  christos       || ((insn & 0xf0) == 0xa0
    616  1.1  christos 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
    617  1.1  christos       || ((insn & 0xf0) == 0xb0
    618  1.1  christos 	  && (insn & 0x0c) >> 2 != (insn & 0x03))
    619  1.1  christos       || (insn & 0xff) == 0xcb
    620  1.1  christos       || (insn & 0xfc) == 0xd0
    621  1.1  christos       || (insn & 0xfc) == 0xd4
    622  1.1  christos       || (insn & 0xfc) == 0xd8
    623  1.1  christos       || (insn & 0xf0) == 0xe0
    624  1.1  christos       || (insn & 0xff) == 0xff)
    625  1.1  christos     {
    626  1.1  christos       consume = 1;
    627  1.1  christos     }
    628  1.1  christos 
    629  1.1  christos   /* These are two byte insns.  */
    630  1.1  christos   else if ((insn & 0xf0) == 0x80
    631  1.1  christos 	   || (insn & 0xf0) == 0x90
    632  1.1  christos 	   || (insn & 0xf0) == 0xa0
    633  1.1  christos 	   || (insn & 0xf0) == 0xb0
    634  1.1  christos 	   || (insn & 0xfc) == 0x20
    635  1.1  christos 	   || (insn & 0xfc) == 0x28
    636  1.1  christos 	   || (insn & 0xf3) == 0x43
    637  1.1  christos 	   || (insn & 0xf3) == 0x42
    638  1.1  christos 	   || (insn & 0xfc) == 0x58
    639  1.1  christos 	   || (insn & 0xfc) == 0x5c
    640  1.1  christos 	   || ((insn & 0xf0) == 0xc0
    641  1.1  christos 	       && (insn & 0xff) != 0xcb
    642  1.1  christos 	       && (insn & 0xff) != 0xcc
    643  1.1  christos 	       && (insn & 0xff) != 0xcd)
    644  1.1  christos 	   || (insn & 0xff) == 0xf0
    645  1.1  christos 	   || (insn & 0xff) == 0xf1
    646  1.1  christos 	   || (insn & 0xff) == 0xf2
    647  1.1  christos 	   || (insn & 0xff) == 0xf3
    648  1.1  christos 	   || (insn & 0xff) == 0xf4
    649  1.1  christos 	   || (insn & 0xff) == 0xf5
    650  1.1  christos 	   || (insn & 0xff) == 0xf6)
    651  1.1  christos     {
    652  1.1  christos       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
    653  1.1  christos       if (status != 0)
    654  1.1  christos 	{
    655  1.1  christos 	  (*info->memory_error_func) (status, memaddr, info);
    656  1.1  christos 	  return -1;
    657  1.1  christos 	}
    658  1.1  christos       insn = bfd_getb16 (buffer);
    659  1.1  christos       consume = 2;
    660  1.1  christos     }
    661  1.1  christos 
    662  1.1  christos   /* These are three byte insns.  */
    663  1.1  christos   else if ((insn & 0xff) == 0xf8
    664  1.1  christos 	   || (insn & 0xff) == 0xcc
    665  1.1  christos 	   || (insn & 0xff) == 0xf9
    666  1.1  christos 	   || (insn & 0xf3) == 0x01
    667  1.1  christos 	   || (insn & 0xf3) == 0x02
    668  1.1  christos 	   || (insn & 0xf3) == 0x03
    669  1.1  christos 	   || (insn & 0xfc) == 0x24
    670  1.1  christos 	   || (insn & 0xfc) == 0x2c
    671  1.1  christos 	   || (insn & 0xfc) == 0x30
    672  1.1  christos 	   || (insn & 0xfc) == 0x34
    673  1.1  christos 	   || (insn & 0xfc) == 0x38
    674  1.1  christos 	   || (insn & 0xff) == 0xde
    675  1.1  christos 	   || (insn & 0xff) == 0xdf
    676  1.1  christos 	   || (insn & 0xff) == 0xf9
    677  1.1  christos 	   || (insn & 0xff) == 0xcc)
    678  1.1  christos     {
    679  1.1  christos       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
    680  1.1  christos       if (status != 0)
    681  1.1  christos 	{
    682  1.1  christos 	  (*info->memory_error_func) (status, memaddr, info);
    683  1.1  christos 	  return -1;
    684  1.1  christos 	}
    685  1.1  christos       insn = bfd_getb16 (buffer);
    686  1.1  christos       insn <<= 8;
    687  1.1  christos       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
    688  1.1  christos       if (status != 0)
    689  1.1  christos 	{
    690  1.1  christos 	  (*info->memory_error_func) (status, memaddr, info);
    691  1.1  christos 	  return -1;
    692  1.1  christos 	}
    693  1.1  christos       insn |= *(unsigned char *) buffer;
    694  1.1  christos       consume = 3;
    695  1.1  christos     }
    696  1.1  christos 
    697  1.1  christos   /* These are four byte insns.  */
    698  1.1  christos   else if ((insn & 0xff) == 0xfa
    699  1.1  christos 	   || (insn & 0xff) == 0xf7
    700  1.1  christos 	   || (insn & 0xff) == 0xfb)
    701  1.1  christos     {
    702  1.1  christos       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
    703  1.1  christos       if (status != 0)
    704  1.1  christos 	{
    705  1.1  christos 	  (*info->memory_error_func) (status, memaddr, info);
    706  1.1  christos 	  return -1;
    707  1.1  christos 	}
    708  1.1  christos       insn = bfd_getb32 (buffer);
    709  1.1  christos       consume = 4;
    710  1.1  christos     }
    711  1.1  christos 
    712  1.1  christos   /* These are five byte insns.  */
    713  1.1  christos   else if ((insn & 0xff) == 0xcd
    714  1.1  christos 	   || (insn & 0xff) == 0xdc)
    715  1.1  christos     {
    716  1.1  christos       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
    717  1.1  christos       if (status != 0)
    718  1.1  christos 	{
    719  1.1  christos 	  (*info->memory_error_func) (status, memaddr, info);
    720  1.1  christos 	  return -1;
    721  1.1  christos 	}
    722  1.1  christos       insn = bfd_getb32 (buffer);
    723  1.1  christos       consume = 5;
    724  1.1  christos     }
    725  1.1  christos 
    726  1.1  christos   /* These are six byte insns.  */
    727  1.1  christos   else if ((insn & 0xff) == 0xfd
    728  1.1  christos 	   || (insn & 0xff) == 0xfc)
    729  1.1  christos     {
    730  1.1  christos       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
    731  1.1  christos       if (status != 0)
    732  1.1  christos 	{
    733  1.1  christos 	  (*info->memory_error_func) (status, memaddr, info);
    734  1.1  christos 	  return -1;
    735  1.1  christos 	}
    736  1.1  christos 
    737  1.1  christos       insn = bfd_getb32 (buffer);
    738  1.1  christos       consume = 6;
    739  1.1  christos     }
    740  1.1  christos 
    741  1.1  christos   /* Else its a seven byte insns (in theory).  */
    742  1.1  christos   else
    743  1.1  christos     {
    744  1.1  christos       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
    745  1.1  christos       if (status != 0)
    746  1.1  christos 	{
    747  1.1  christos 	  (*info->memory_error_func) (status, memaddr, info);
    748  1.1  christos 	  return -1;
    749  1.1  christos 	}
    750  1.1  christos 
    751  1.1  christos       insn = bfd_getb32 (buffer);
    752  1.1  christos       consume = 7;
    753  1.1  christos       /* Handle the 5-byte extended instruction codes.  */
    754  1.1  christos       if ((insn & 0xfff80000) == 0xfe800000)
    755  1.1  christos 	consume = 5;
    756  1.1  christos     }
    757  1.1  christos 
    758  1.1  christos   disassemble (memaddr, info, insn, consume);
    759  1.1  christos 
    760  1.1  christos   return consume;
    761  1.1  christos }
    762