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