Back to index

cell-binutils  2.17cvs20070401
m10300-dis.c
Go to the documentation of this file.
00001 /* Disassemble MN10300 instructions.
00002    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005
00003    Free Software Foundation, Inc.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
00018    MA 02110-1301, USA.  */
00019 
00020 #include <stdio.h>
00021 
00022 #include "sysdep.h"
00023 #include "opcode/mn10300.h"
00024 #include "dis-asm.h"
00025 #include "opintl.h"
00026 
00027 #define HAVE_AM33_2 (info->mach == AM33_2)
00028 #define HAVE_AM33   (info->mach == AM33 || HAVE_AM33_2)
00029 #define HAVE_AM30   (info->mach == AM30)
00030 
00031 static void
00032 disassemble (bfd_vma memaddr,
00033             struct disassemble_info *info,
00034             unsigned long insn,
00035             unsigned int size)
00036 {
00037   struct mn10300_opcode *op = (struct mn10300_opcode *) mn10300_opcodes;
00038   const struct mn10300_operand *operand;
00039   bfd_byte buffer[4];
00040   unsigned long extension = 0;
00041   int status, match = 0;
00042 
00043   /* Find the opcode.  */
00044   while (op->name)
00045     {
00046       int mysize, extra_shift;
00047 
00048       if (op->format == FMT_S0)
00049        mysize = 1;
00050       else if (op->format == FMT_S1
00051               || op->format == FMT_D0)
00052        mysize = 2;
00053       else if (op->format == FMT_S2
00054               || op->format == FMT_D1)
00055        mysize = 3;
00056       else if (op->format == FMT_S4)
00057        mysize = 5;
00058       else if (op->format == FMT_D2)
00059        mysize = 4;
00060       else if (op->format == FMT_D3)
00061        mysize = 5;
00062       else if (op->format == FMT_D4)
00063        mysize = 6;
00064       else if (op->format == FMT_D6)
00065        mysize = 3;
00066       else if (op->format == FMT_D7 || op->format == FMT_D10)
00067        mysize = 4;
00068       else if (op->format == FMT_D8)
00069        mysize = 6;
00070       else if (op->format == FMT_D9)
00071        mysize = 7;
00072       else
00073        mysize = 7;
00074 
00075       if ((op->mask & insn) == op->opcode
00076          && size == (unsigned int) mysize
00077          && (op->machine == 0
00078              || (op->machine == AM33_2 && HAVE_AM33_2)
00079              || (op->machine == AM33 && HAVE_AM33)
00080              || (op->machine == AM30 && HAVE_AM30)))
00081        {
00082          const unsigned char *opindex_ptr;
00083          unsigned int nocomma;
00084          int paren = 0;
00085 
00086          if (op->format == FMT_D1 || op->format == FMT_S1)
00087            extra_shift = 8;
00088          else if (op->format == FMT_D2 || op->format == FMT_D4
00089                  || op->format == FMT_S2 || op->format == FMT_S4
00090                  || op->format == FMT_S6 || op->format == FMT_D5)
00091            extra_shift = 16;
00092          else if (op->format == FMT_D7
00093                  || op->format == FMT_D8
00094                  || op->format == FMT_D9)
00095            extra_shift = 8;
00096          else
00097            extra_shift = 0;
00098 
00099          if (size == 1 || size == 2)
00100            extension = 0;
00101 
00102          else if (size == 3
00103                  && (op->format == FMT_D1
00104                      || op->opcode == 0xdf0000
00105                      || op->opcode == 0xde0000))
00106            extension = 0;
00107 
00108          else if (size == 3
00109                  && op->format == FMT_D6)
00110            extension = 0;
00111 
00112          else if (size == 3)
00113            {
00114              insn &= 0xff0000;
00115              status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
00116              if (status != 0)
00117               {
00118                 (*info->memory_error_func) (status, memaddr, info);
00119                 return;
00120               }
00121 
00122              insn |= bfd_getl16 (buffer);
00123              extension = 0;
00124            }
00125          else if (size == 4
00126                  && (op->opcode == 0xfaf80000
00127                      || op->opcode == 0xfaf00000
00128                      || op->opcode == 0xfaf40000))
00129            extension = 0;
00130 
00131          else if (size == 4
00132                  && (op->format == FMT_D7
00133                      || op->format == FMT_D10))
00134            extension = 0;
00135 
00136          else if (size == 4)
00137            {
00138              insn &= 0xffff0000;
00139              status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
00140              if (status != 0)
00141               {
00142                 (*info->memory_error_func) (status, memaddr, info);
00143                 return;
00144               }
00145 
00146              insn |= bfd_getl16 (buffer);
00147              extension = 0;
00148            }
00149          else if (size == 5 && op->opcode == 0xdc000000)
00150            {
00151              unsigned long temp = 0;
00152 
00153              status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
00154              if (status != 0)
00155               {
00156                 (*info->memory_error_func) (status, memaddr, info);
00157                 return;
00158               }
00159              temp |= bfd_getl32 (buffer);
00160 
00161              insn &= 0xff000000;
00162              insn |= (temp & 0xffffff00) >> 8;
00163              extension = temp & 0xff;
00164            }
00165          else if (size == 5 && op->format == FMT_D3)
00166            {
00167              status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
00168              if (status != 0)
00169               {
00170                 (*info->memory_error_func) (status, memaddr, info);
00171                 return;
00172               }
00173              insn &= 0xffff0000;
00174              insn |= bfd_getl16 (buffer);
00175 
00176              status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
00177              if (status != 0)
00178               {
00179                 (*info->memory_error_func) (status, memaddr, info);
00180                 return;
00181               }
00182              extension = *(unsigned char *) buffer;
00183            }
00184          else if (size == 5)
00185            {
00186              unsigned long temp = 0;
00187 
00188              status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
00189              if (status != 0)
00190               {
00191                 (*info->memory_error_func) (status, memaddr, info);
00192                 return;
00193               }
00194              temp |= bfd_getl16 (buffer);
00195 
00196              insn &= 0xff0000ff;
00197              insn |= temp << 8;
00198 
00199              status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
00200              if (status != 0)
00201               {
00202                 (*info->memory_error_func) (status, memaddr, info);
00203                 return;
00204               }
00205              extension = *(unsigned char *) buffer;
00206            }
00207          else if (size == 6 && op->format == FMT_D8)
00208            {
00209              insn &= 0xffffff00;
00210              status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
00211              if (status != 0)
00212               {
00213                 (*info->memory_error_func) (status, memaddr, info);
00214                 return;
00215               }
00216              insn |= *(unsigned char *) buffer;
00217 
00218              status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
00219              if (status != 0)
00220               {
00221                 (*info->memory_error_func) (status, memaddr, info);
00222                 return;
00223               }
00224              extension = bfd_getl16 (buffer);
00225            }
00226          else if (size == 6)
00227            {
00228              unsigned long temp = 0;
00229 
00230              status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
00231              if (status != 0)
00232               {
00233                 (*info->memory_error_func) (status, memaddr, info);
00234                 return;
00235               }
00236              temp |= bfd_getl32 (buffer);
00237 
00238              insn &= 0xffff0000;
00239              insn |= (temp >> 16) & 0xffff;
00240              extension = temp & 0xffff;
00241            }
00242          else if (size == 7 && op->format == FMT_D9)
00243            {
00244              insn &= 0xffffff00;
00245              status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
00246              if (status != 0)
00247               {
00248                 (*info->memory_error_func) (status, memaddr, info);
00249                 return;
00250               }
00251              extension = bfd_getl32 (buffer);
00252              insn |= (extension & 0xff000000) >> 24;
00253              extension &= 0xffffff;
00254            }
00255          else if (size == 7 && op->opcode == 0xdd000000)
00256            {
00257              unsigned long temp = 0;
00258 
00259              status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
00260              if (status != 0)
00261               {
00262                 (*info->memory_error_func) (status, memaddr, info);
00263                 return;
00264               }
00265              temp |= bfd_getl32 (buffer);
00266 
00267              insn &= 0xff000000;
00268              insn |= (temp >> 8) & 0xffffff;
00269              extension = (temp & 0xff) << 16;
00270 
00271              status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
00272              if (status != 0)
00273               {
00274                 (*info->memory_error_func) (status, memaddr, info);
00275                 return;
00276               }
00277              extension |= bfd_getb16 (buffer);
00278            }
00279          else if (size == 7)
00280            {
00281              unsigned long temp = 0;
00282 
00283              status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
00284              if (status != 0)
00285               {
00286                 (*info->memory_error_func) (status, memaddr, info);
00287                 return;
00288               }
00289              temp |= bfd_getl32 (buffer);
00290 
00291              insn &= 0xffff0000;
00292              insn |= (temp >> 16) & 0xffff;
00293              extension = (temp & 0xffff) << 8;
00294 
00295              status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
00296              if (status != 0)
00297               {
00298                 (*info->memory_error_func) (status, memaddr, info);
00299                 return;
00300               }
00301              extension |= *(unsigned char *) buffer;
00302            }
00303 
00304          match = 1;
00305          (*info->fprintf_func) (info->stream, "%s\t", op->name);
00306 
00307          /* Now print the operands.  */
00308          for (opindex_ptr = op->operands, nocomma = 1;
00309               *opindex_ptr != 0;
00310               opindex_ptr++)
00311            {
00312              unsigned long value;
00313 
00314              operand = &mn10300_operands[*opindex_ptr];
00315 
00316              /* If this operand is a PLUS (autoincrement), then do not emit
00317                a comma before emitting the plus.  */
00318              if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
00319               nocomma = 1;
00320 
00321              if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
00322               {
00323                 unsigned long temp;
00324 
00325                 value = insn & ((1 << operand->bits) - 1);
00326                 value <<= (32 - operand->bits);
00327                 temp = extension >> operand->shift;
00328                 temp &= ((1 << (32 - operand->bits)) - 1);
00329                 value |= temp;
00330                 value = ((value ^ (((unsigned long) 1) << 31))
00331                         - (((unsigned long) 1) << 31));
00332               }
00333              else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
00334               {
00335                 unsigned long temp;
00336 
00337                 value = insn & ((1 << operand->bits) - 1);
00338                 value <<= (24 - operand->bits);
00339                 temp = extension >> operand->shift;
00340                 temp &= ((1 << (24 - operand->bits)) - 1);
00341                 value |= temp;
00342                 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
00343                   value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
00344               }
00345              else if ((operand->flags & (MN10300_OPERAND_FSREG
00346                                      | MN10300_OPERAND_FDREG)))
00347               {
00348                 /* See m10300-opc.c just before #define FSM0 for an
00349                    explanation of these variables.  Note that
00350                    FMT-implied shifts are not taken into account for
00351                    FP registers.  */
00352                 unsigned long mask_low, mask_high;
00353                 int shl_low, shr_high, shl_high;
00354 
00355                 switch (operand->bits)
00356                   {
00357                   case 5:
00358                     /* Handle regular FP registers.  */
00359                     if (operand->shift >= 0)
00360                      {
00361                        /* This is an `m' register.  */
00362                        shl_low = operand->shift;
00363                        shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
00364                      }
00365                     else
00366                      {
00367                        /* This is an `n' register.  */
00368                        shl_low = -operand->shift;
00369                        shl_high = shl_low / 4;
00370                      }
00371                     mask_low = 0x0f;
00372                     mask_high = 0x10;
00373                     shr_high = 4;
00374                     break;
00375 
00376                   case 3:
00377                     /* Handle accumulators.  */
00378                     shl_low = -operand->shift;
00379                     shl_high = 0;
00380                     mask_low = 0x03;
00381                     mask_high = 0x04;
00382                     shr_high = 2;
00383                     break;
00384 
00385                   default:
00386                     abort ();
00387                   }
00388                 value = ((((insn >> shl_high) << shr_high) & mask_high)
00389                         | ((insn >> shl_low) & mask_low));
00390               }
00391              else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
00392               value = ((extension >> (operand->shift))
00393                       & ((1 << operand->bits) - 1));
00394 
00395              else
00396               value = ((insn >> (operand->shift))
00397                       & ((1 << operand->bits) - 1));
00398 
00399              if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
00400                 /* These are properly extended by the code above.  */
00401                 && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
00402               value = ((value ^ (((unsigned long) 1) << (operand->bits - 1)))
00403                       - (((unsigned long) 1) << (operand->bits - 1)));
00404 
00405              if (!nocomma
00406                 && (!paren
00407                     || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
00408               (*info->fprintf_func) (info->stream, ",");
00409 
00410              nocomma = 0;
00411 
00412              if ((operand->flags & MN10300_OPERAND_DREG) != 0)
00413               {
00414                 value = ((insn >> (operand->shift + extra_shift))
00415                         & ((1 << operand->bits) - 1));
00416                 (*info->fprintf_func) (info->stream, "d%d", (int) value);
00417               }
00418 
00419              else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
00420               {
00421                 value = ((insn >> (operand->shift + extra_shift))
00422                         & ((1 << operand->bits) - 1));
00423                 (*info->fprintf_func) (info->stream, "a%d", (int) value);
00424               }
00425 
00426              else if ((operand->flags & MN10300_OPERAND_SP) != 0)
00427               (*info->fprintf_func) (info->stream, "sp");
00428 
00429              else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
00430               (*info->fprintf_func) (info->stream, "psw");
00431 
00432              else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
00433               (*info->fprintf_func) (info->stream, "mdr");
00434 
00435              else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
00436               {
00437                 value = ((insn >> (operand->shift + extra_shift))
00438                         & ((1 << operand->bits) - 1));
00439                 if (value < 8)
00440                   (*info->fprintf_func) (info->stream, "r%d", (int) value);
00441                 else if (value < 12)
00442                   (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
00443                 else
00444                   (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
00445               }
00446 
00447              else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
00448               {
00449                 value = ((insn >> (operand->shift + extra_shift))
00450                         & ((1 << operand->bits) - 1));
00451                 if (value == 0)
00452                   (*info->fprintf_func) (info->stream, "sp");
00453                 else
00454                   (*info->fprintf_func) (info->stream, "xr%d", (int) value);
00455               }
00456 
00457              else if ((operand->flags & MN10300_OPERAND_FSREG) != 0)
00458               (*info->fprintf_func) (info->stream, "fs%d", (int) value);
00459 
00460              else if ((operand->flags & MN10300_OPERAND_FDREG) != 0)
00461               (*info->fprintf_func) (info->stream, "fd%d", (int) value);
00462 
00463              else if ((operand->flags & MN10300_OPERAND_FPCR) != 0)
00464               (*info->fprintf_func) (info->stream, "fpcr");
00465 
00466              else if ((operand->flags & MN10300_OPERAND_USP) != 0)
00467               (*info->fprintf_func) (info->stream, "usp");
00468 
00469              else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
00470               (*info->fprintf_func) (info->stream, "ssp");
00471 
00472              else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
00473               (*info->fprintf_func) (info->stream, "msp");
00474 
00475              else if ((operand->flags & MN10300_OPERAND_PC) != 0)
00476               (*info->fprintf_func) (info->stream, "pc");
00477 
00478              else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
00479               (*info->fprintf_func) (info->stream, "epsw");
00480 
00481              else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
00482               (*info->fprintf_func) (info->stream, "+");
00483 
00484              else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
00485               {
00486                 if (paren)
00487                   (*info->fprintf_func) (info->stream, ")");
00488                 else
00489                   {
00490                     (*info->fprintf_func) (info->stream, "(");
00491                     nocomma = 1;
00492                   }
00493                 paren = !paren;
00494               }
00495 
00496              else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
00497               (*info->print_address_func) ((long) value + memaddr, info);
00498 
00499              else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
00500               (*info->print_address_func) (value, info);
00501 
00502              else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
00503               {
00504                 int comma = 0;
00505 
00506                 (*info->fprintf_func) (info->stream, "[");
00507                 if (value & 0x80)
00508                   {
00509                     (*info->fprintf_func) (info->stream, "d2");
00510                     comma = 1;
00511                   }
00512 
00513                 if (value & 0x40)
00514                   {
00515                     if (comma)
00516                      (*info->fprintf_func) (info->stream, ",");
00517                     (*info->fprintf_func) (info->stream, "d3");
00518                     comma = 1;
00519                   }
00520 
00521                 if (value & 0x20)
00522                   {
00523                     if (comma)
00524                      (*info->fprintf_func) (info->stream, ",");
00525                     (*info->fprintf_func) (info->stream, "a2");
00526                     comma = 1;
00527                   }
00528 
00529                 if (value & 0x10)
00530                   {
00531                     if (comma)
00532                      (*info->fprintf_func) (info->stream, ",");
00533                     (*info->fprintf_func) (info->stream, "a3");
00534                     comma = 1;
00535                   }
00536 
00537                 if (value & 0x08)
00538                   {
00539                     if (comma)
00540                      (*info->fprintf_func) (info->stream, ",");
00541                     (*info->fprintf_func) (info->stream, "other");
00542                     comma = 1;
00543                   }
00544 
00545                 if (value & 0x04)
00546                   {
00547                     if (comma)
00548                      (*info->fprintf_func) (info->stream, ",");
00549                     (*info->fprintf_func) (info->stream, "exreg0");
00550                     comma = 1;
00551                   }
00552                 if (value & 0x02)
00553                   {
00554                     if (comma)
00555                      (*info->fprintf_func) (info->stream, ",");
00556                     (*info->fprintf_func) (info->stream, "exreg1");
00557                     comma = 1;
00558                   }
00559                 if (value & 0x01)
00560                   {
00561                     if (comma)
00562                      (*info->fprintf_func) (info->stream, ",");
00563                     (*info->fprintf_func) (info->stream, "exother");
00564                     comma = 1;
00565                   }
00566                 (*info->fprintf_func) (info->stream, "]");
00567               }
00568 
00569              else
00570               (*info->fprintf_func) (info->stream, "%ld", (long) value);
00571            }
00572          /* All done. */
00573          break;
00574        }
00575       op++;
00576     }
00577 
00578   if (!match)
00579     /* xgettext:c-format */
00580     (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
00581 }
00582 
00583 int
00584 print_insn_mn10300 (bfd_vma memaddr, struct disassemble_info *info)
00585 {
00586   int status;
00587   bfd_byte buffer[4];
00588   unsigned long insn;
00589   unsigned int consume;
00590 
00591   /* First figure out how big the opcode is.  */
00592   status = (*info->read_memory_func) (memaddr, buffer, 1, info);
00593   if (status != 0)
00594     {
00595       (*info->memory_error_func) (status, memaddr, info);
00596       return -1;
00597     }
00598   insn = *(unsigned char *) buffer;
00599 
00600   /* These are one byte insns.  */
00601   if ((insn & 0xf3) == 0x00
00602       || (insn & 0xf0) == 0x10
00603       || (insn & 0xfc) == 0x3c
00604       || (insn & 0xf3) == 0x41
00605       || (insn & 0xf3) == 0x40
00606       || (insn & 0xfc) == 0x50
00607       || (insn & 0xfc) == 0x54
00608       || (insn & 0xf0) == 0x60
00609       || (insn & 0xf0) == 0x70
00610       || ((insn & 0xf0) == 0x80
00611          && (insn & 0x0c) >> 2 != (insn & 0x03))
00612       || ((insn & 0xf0) == 0x90
00613          && (insn & 0x0c) >> 2 != (insn & 0x03))
00614       || ((insn & 0xf0) == 0xa0
00615          && (insn & 0x0c) >> 2 != (insn & 0x03))
00616       || ((insn & 0xf0) == 0xb0
00617          && (insn & 0x0c) >> 2 != (insn & 0x03))
00618       || (insn & 0xff) == 0xcb
00619       || (insn & 0xfc) == 0xd0
00620       || (insn & 0xfc) == 0xd4
00621       || (insn & 0xfc) == 0xd8
00622       || (insn & 0xf0) == 0xe0
00623       || (insn & 0xff) == 0xff)
00624     {
00625       consume = 1;
00626     }
00627 
00628   /* These are two byte insns.  */
00629   else if ((insn & 0xf0) == 0x80
00630           || (insn & 0xf0) == 0x90
00631           || (insn & 0xf0) == 0xa0
00632           || (insn & 0xf0) == 0xb0
00633           || (insn & 0xfc) == 0x20
00634           || (insn & 0xfc) == 0x28
00635           || (insn & 0xf3) == 0x43
00636           || (insn & 0xf3) == 0x42
00637           || (insn & 0xfc) == 0x58
00638           || (insn & 0xfc) == 0x5c
00639           || ((insn & 0xf0) == 0xc0
00640               && (insn & 0xff) != 0xcb
00641               && (insn & 0xff) != 0xcc
00642               && (insn & 0xff) != 0xcd)
00643           || (insn & 0xff) == 0xf0
00644           || (insn & 0xff) == 0xf1
00645           || (insn & 0xff) == 0xf2
00646           || (insn & 0xff) == 0xf3
00647           || (insn & 0xff) == 0xf4
00648           || (insn & 0xff) == 0xf5
00649           || (insn & 0xff) == 0xf6)
00650     {
00651       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
00652       if (status != 0)
00653        {
00654          (*info->memory_error_func) (status, memaddr, info);
00655          return -1;
00656        }
00657       insn = bfd_getb16 (buffer);
00658       consume = 2;
00659     }
00660 
00661   /* These are three byte insns.  */
00662   else if ((insn & 0xff) == 0xf8
00663           || (insn & 0xff) == 0xcc
00664           || (insn & 0xff) == 0xf9
00665           || (insn & 0xf3) == 0x01
00666           || (insn & 0xf3) == 0x02
00667           || (insn & 0xf3) == 0x03
00668           || (insn & 0xfc) == 0x24
00669           || (insn & 0xfc) == 0x2c
00670           || (insn & 0xfc) == 0x30
00671           || (insn & 0xfc) == 0x34
00672           || (insn & 0xfc) == 0x38
00673           || (insn & 0xff) == 0xde
00674           || (insn & 0xff) == 0xdf
00675           || (insn & 0xff) == 0xf9
00676           || (insn & 0xff) == 0xcc)
00677     {
00678       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
00679       if (status != 0)
00680        {
00681          (*info->memory_error_func) (status, memaddr, info);
00682          return -1;
00683        }
00684       insn = bfd_getb16 (buffer);
00685       insn <<= 8;
00686       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
00687       if (status != 0)
00688        {
00689          (*info->memory_error_func) (status, memaddr, info);
00690          return -1;
00691        }
00692       insn |= *(unsigned char *) buffer;
00693       consume = 3;
00694     }
00695 
00696   /* These are four byte insns.  */
00697   else if ((insn & 0xff) == 0xfa
00698           || (insn & 0xff) == 0xf7
00699           || (insn & 0xff) == 0xfb)
00700     {
00701       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
00702       if (status != 0)
00703        {
00704          (*info->memory_error_func) (status, memaddr, info);
00705          return -1;
00706        }
00707       insn = bfd_getb32 (buffer);
00708       consume = 4;
00709     }
00710 
00711   /* These are five byte insns.  */
00712   else if ((insn & 0xff) == 0xcd
00713           || (insn & 0xff) == 0xdc)
00714     {
00715       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
00716       if (status != 0)
00717        {
00718          (*info->memory_error_func) (status, memaddr, info);
00719          return -1;
00720        }
00721       insn = bfd_getb32 (buffer);
00722       consume = 5;
00723     }
00724 
00725   /* These are six byte insns.  */
00726   else if ((insn & 0xff) == 0xfd
00727           || (insn & 0xff) == 0xfc)
00728     {
00729       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
00730       if (status != 0)
00731        {
00732          (*info->memory_error_func) (status, memaddr, info);
00733          return -1;
00734        }
00735 
00736       insn = bfd_getb32 (buffer);
00737       consume = 6;
00738     }
00739 
00740   /* Else its a seven byte insns (in theory).  */
00741   else
00742     {
00743       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
00744       if (status != 0)
00745        {
00746          (*info->memory_error_func) (status, memaddr, info);
00747          return -1;
00748        }
00749 
00750       insn = bfd_getb32 (buffer);
00751       consume = 7;
00752       /* Handle the 5-byte extended instruction codes.  */
00753       if ((insn & 0xfff80000) == 0xfe800000)
00754        consume = 5;
00755     }
00756 
00757   disassemble (memaddr, info, insn, consume);
00758 
00759   return consume;
00760 }