Back to index

cell-binutils  2.17cvs20070401
mcore-dis.c
Go to the documentation of this file.
00001 /* Disassemble Motorola M*Core instructions.
00002    Copyright 1993, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00017 
00018 #include "sysdep.h"
00019 #include <stdio.h>
00020 #define STATIC_TABLE
00021 #define DEFINE_TABLE
00022 
00023 #include "mcore-opc.h"
00024 #include "dis-asm.h"
00025 
00026 /* Mask for each mcore_opclass: */
00027 static const unsigned short imsk[] = {
00028     /* O0  */ 0xFFFF,
00029     /* OT  */ 0xFFFC,
00030     /* O1  */ 0xFFF0,
00031     /* OC  */ 0xFE00,
00032     /* O2  */ 0xFF00,
00033     /* X1  */ 0xFFF0,
00034     /* OI  */ 0xFE00,
00035     /* OB  */ 0xFE00,
00036 
00037     /* OMa */ 0xFFF0,
00038     /* SI  */ 0xFE00,
00039     /* I7  */ 0xF800,
00040     /* LS  */ 0xF000,
00041     /* BR  */ 0xF800,
00042     /* BL  */ 0xFF00,
00043     /* LR  */ 0xF000,
00044     /* LJ  */ 0xFF00,
00045 
00046     /* RM  */ 0xFFF0,
00047     /* RQ  */ 0xFFF0,
00048     /* JSR */ 0xFFF0,
00049     /* JMP */ 0xFFF0,
00050     /* OBRa*/ 0xFFF0,
00051     /* OBRb*/ 0xFF80,
00052     /* OBRc*/ 0xFF00,
00053     /* OBR2*/ 0xFE00,
00054 
00055     /* O1R1*/ 0xFFF0,
00056     /* OMb */ 0xFF80,
00057     /* OMc */ 0xFF00,
00058     /* SIa */ 0xFE00,
00059 
00060   /* MULSH */ 0xFF00,
00061   /* OPSR  */ 0xFFF8,   /* psrset/psrclr */
00062 
00063     /* JC  */ 0,            /* JC,JU,JL don't appear in object */
00064     /* JU  */ 0,
00065     /* JL  */ 0,
00066     /* RSI */ 0,
00067     /* DO21*/ 0,
00068     /* OB2 */ 0             /* OB2 won't appear in object.  */
00069 };
00070 
00071 static const char *grname[] = {
00072  "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
00073  "r8",  "r9", "r10", "r11", "r12", "r13", "r14", "r15"
00074 };
00075 
00076 static const char X[] = "??";
00077 
00078 static const char *crname[] = {
00079   "psr",  "vbr", "epsr", "fpsr", "epc",  "fpc",  "ss0",  "ss1",
00080   "ss2",  "ss3", "ss4",  "gcr",  "gsr",     X,      X,      X,
00081      X,      X,      X,      X,      X,     X,      X,      X,
00082      X,      X,      X,      X,      X,     X,      X,      X
00083 };
00084 
00085 static const unsigned isiz[] = { 2, 0, 1, 0 };
00086 
00087 int
00088 print_insn_mcore (memaddr, info)
00089      bfd_vma memaddr;
00090      struct disassemble_info *info;
00091 {
00092   unsigned char ibytes[4];
00093   fprintf_ftype fprintf = info->fprintf_func;
00094   void *stream = info->stream;
00095   unsigned short inst;
00096   const mcore_opcode_info *op;
00097   int status;
00098 
00099   info->bytes_per_chunk = 2;
00100 
00101   status = info->read_memory_func (memaddr, ibytes, 2, info);
00102 
00103   if (status != 0)
00104     {
00105       info->memory_error_func (status, memaddr, info);
00106       return -1;
00107     }
00108 
00109   if (info->endian == BFD_ENDIAN_BIG)
00110     inst = (ibytes[0] << 8) | ibytes[1];
00111   else if (info->endian == BFD_ENDIAN_LITTLE)
00112     inst = (ibytes[1] << 8) | ibytes[0];
00113   else
00114     abort ();
00115 
00116   /* Just a linear search of the table.  */
00117   for (op = mcore_table; op->name != 0; op++)
00118     if (op->inst == (inst & imsk[op->opclass]))
00119       break;
00120 
00121   if (op->name == 0)
00122     fprintf (stream, ".short 0x%04x", inst);
00123   else
00124     {
00125       const char *name = grname[inst & 0x0F];
00126 
00127       fprintf (stream, "%s", op->name);
00128 
00129       switch (op->opclass)
00130        {
00131        case O0:
00132          break;
00133 
00134        case OT:
00135          fprintf (stream, "\t%d", inst & 0x3);
00136          break;
00137 
00138        case O1:
00139        case JMP:
00140        case JSR:
00141          fprintf (stream, "\t%s", name);
00142          break;
00143 
00144        case OC:
00145          fprintf (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]);
00146          break;
00147 
00148        case O1R1:
00149          fprintf (stream, "\t%s, r1", name);
00150          break;
00151 
00152        case MULSH:
00153        case O2:
00154          fprintf (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]);
00155          break;
00156 
00157        case X1:
00158          fprintf (stream, "\tr1, %s", name);
00159          break;
00160 
00161        case OI:
00162          fprintf (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1);
00163          break;
00164 
00165        case RM:
00166          fprintf (stream, "\t%s-r15, (r0)", name);
00167          break;
00168 
00169        case RQ:
00170          fprintf (stream, "\tr4-r7, (%s)", name);
00171          break;
00172 
00173        case OB:
00174        case OBRa:
00175        case OBRb:
00176        case OBRc:
00177        case SI:
00178        case SIa:
00179        case OMa:
00180        case OMb:
00181        case OMc:
00182          fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x1F);
00183          break;
00184 
00185        case I7:
00186          fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x7F);
00187          break;
00188 
00189        case LS:
00190          fprintf (stream, "\t%s, (%s, %d)", grname[(inst >> 8) & 0xF],
00191                  name, ((inst >> 4) & 0xF) << isiz[(inst >> 13) & 3]);
00192          break;
00193 
00194        case BR:
00195          {
00196            long val = inst & 0x3FF;
00197 
00198            if (inst & 0x400)
00199              val |= 0xFFFFFC00;
00200 
00201            fprintf (stream, "\t0x%lx", (long)(memaddr + 2 + (val << 1)));
00202 
00203            if (strcmp (op->name, "bsr") == 0)
00204              {
00205               /* For bsr, we'll try to get a symbol for the target.  */
00206               val = memaddr + 2 + (val << 1);
00207 
00208               if (info->print_address_func && val != 0)
00209                 {
00210                   fprintf (stream, "\t// ");
00211                   info->print_address_func (val, info);
00212                 }
00213              }
00214          }
00215          break;
00216 
00217        case BL:
00218          {
00219            long val;
00220            val = (inst & 0x000F);
00221            fprintf (stream, "\t%s, 0x%lx",
00222                    grname[(inst >> 4) & 0xF], (long)(memaddr - (val << 1)));
00223          }
00224          break;
00225 
00226        case LR:
00227          {
00228            unsigned long val;
00229 
00230            val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
00231 
00232            status = info->read_memory_func (val, ibytes, 4, info);
00233            if (status != 0)
00234              {
00235               info->memory_error_func (status, memaddr, info);
00236               break;
00237              }
00238 
00239            if (info->endian == BFD_ENDIAN_LITTLE)
00240              val = (ibytes[3] << 24) | (ibytes[2] << 16)
00241               | (ibytes[1] << 8) | (ibytes[0]);
00242            else
00243              val = (ibytes[0] << 24) | (ibytes[1] << 16)
00244               | (ibytes[2] << 8) | (ibytes[3]);
00245 
00246            /* Removed [] around literal value to match ABI syntax 12/95.  */
00247            fprintf (stream, "\t%s, 0x%lX", grname[(inst >> 8) & 0xF], val);
00248 
00249            if (val == 0)
00250              fprintf (stream, "\t// from address pool at 0x%lx",
00251                      (long)(memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
00252          }
00253          break;
00254 
00255        case LJ:
00256          {
00257            unsigned long val;
00258 
00259            val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
00260 
00261            status = info->read_memory_func (val, ibytes, 4, info);
00262            if (status != 0)
00263              {
00264               info->memory_error_func (status, memaddr, info);
00265               break;
00266              }
00267 
00268            if (info->endian == BFD_ENDIAN_LITTLE)
00269              val = (ibytes[3] << 24) | (ibytes[2] << 16)
00270               | (ibytes[1] << 8) | (ibytes[0]);
00271            else
00272              val = (ibytes[0] << 24) | (ibytes[1] << 16)
00273               | (ibytes[2] << 8) | (ibytes[3]);
00274 
00275            /* Removed [] around literal value to match ABI syntax 12/95.  */
00276            fprintf (stream, "\t0x%lX", val);
00277            /* For jmpi/jsri, we'll try to get a symbol for the target.  */
00278            if (info->print_address_func && val != 0)
00279              {
00280               fprintf (stream, "\t// ");
00281               info->print_address_func (val, info);
00282              }
00283            else
00284              {
00285               fprintf (stream, "\t// from address pool at 0x%lx",
00286                       (long)(memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
00287              }
00288          }
00289          break;
00290 
00291        case OPSR:
00292          {
00293            static char *fields[] = {
00294              "af", "ie",    "fe",    "fe,ie",
00295              "ee", "ee,ie", "ee,fe", "ee,fe,ie"
00296            };
00297 
00298            fprintf (stream, "\t%s", fields[inst & 0x7]);
00299          }
00300          break;
00301 
00302        default:
00303          /* If the disassembler lags the instruction set.  */
00304          fprintf (stream, "\tundecoded operands, inst is 0x%04x", inst);
00305          break;
00306        }
00307     }
00308 
00309   /* Say how many bytes we consumed.  */
00310   return 2;
00311 }