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