Back to index

cell-binutils  2.17cvs20070401
tic4x-dis.c
Go to the documentation of this file.
00001 /* Print instructions for the Texas TMS320C[34]X, for GDB and GNU Binutils.
00002 
00003    Copyright 2002, 2003, 2005 Free Software Foundation, Inc.
00004 
00005    Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
00020    MA 02110-1301, USA.  */
00021 
00022 #include <math.h>
00023 #include "libiberty.h"
00024 #include "dis-asm.h"
00025 #include "opcode/tic4x.h"
00026 
00027 #define TIC4X_DEBUG 0
00028 
00029 #define TIC4X_HASH_SIZE   11   /* 11 (bits) and above should give unique entries.  */
00030 #define TIC4X_SPESOP_SIZE 8    /* Max 8. ops for special instructions.  */
00031 
00032 typedef enum
00033 {
00034   IMMED_SINT,
00035   IMMED_SUINT,
00036   IMMED_SFLOAT,
00037   IMMED_INT,
00038   IMMED_UINT,
00039   IMMED_FLOAT
00040 }
00041 immed_t;
00042 
00043 typedef enum
00044 {
00045   INDIRECT_SHORT,
00046   INDIRECT_LONG,
00047   INDIRECT_TIC4X
00048 }
00049 indirect_t;
00050 
00051 static int tic4x_version = 0;
00052 static int tic4x_dp = 0;
00053 
00054 static int
00055 tic4x_pc_offset (unsigned int op)
00056 {
00057   /* Determine the PC offset for a C[34]x instruction.
00058      This could be simplified using some boolean algebra
00059      but at the expense of readability.  */
00060   switch (op >> 24)
00061     {
00062     case 0x60:       /* br */
00063     case 0x62:       /* call  (C4x) */
00064     case 0x64:       /* rptb  (C4x) */
00065       return 1;
00066     case 0x61:       /* brd */
00067     case 0x63:       /* laj */
00068     case 0x65:       /* rptbd (C4x) */
00069       return 3;
00070     case 0x66:       /* swi */
00071     case 0x67:
00072       return 0;
00073     default:
00074       break;
00075     }
00076 
00077   switch ((op & 0xffe00000) >> 20)
00078     {
00079     case 0x6a0:      /* bB */
00080     case 0x720: /* callB */
00081     case 0x740: /* trapB */
00082       return 1;
00083 
00084     case 0x6a2: /* bBd */
00085     case 0x6a6: /* bBat */
00086     case 0x6aa: /* bBaf */
00087     case 0x722:      /* lajB */
00088     case 0x748: /* latB */
00089     case 0x798: /* rptbd */
00090       return 3;
00091 
00092     default:
00093       break;
00094     }
00095 
00096   switch ((op & 0xfe200000) >> 20)
00097     {
00098     case 0x6e0:      /* dbB */
00099       return 1;
00100 
00101     case 0x6e2:      /* dbBd */
00102       return 3;
00103 
00104     default:
00105       break;
00106     }
00107 
00108   return 0;
00109 }
00110 
00111 static int
00112 tic4x_print_char (struct disassemble_info * info, char ch)
00113 {
00114   if (info != NULL)
00115     (*info->fprintf_func) (info->stream, "%c", ch);
00116   return 1;
00117 }
00118 
00119 static int
00120 tic4x_print_str (struct disassemble_info *info, char *str)
00121 {
00122   if (info != NULL)
00123     (*info->fprintf_func) (info->stream, "%s", str);
00124   return 1;
00125 }
00126 
00127 static int
00128 tic4x_print_register (struct disassemble_info *info, unsigned long regno)
00129 {
00130   static tic4x_register_t ** registertable = NULL;
00131   unsigned int i;
00132 
00133   if (registertable == NULL)
00134     {
00135       registertable = xmalloc (sizeof (tic4x_register_t *) * REG_TABLE_SIZE);
00136       for (i = 0; i < tic3x_num_registers; i++)
00137        registertable[tic3x_registers[i].regno] = (tic4x_register_t *) (tic3x_registers + i);
00138       if (IS_CPU_TIC4X (tic4x_version))
00139        {
00140          /* Add C4x additional registers, overwriting
00141             any C3x registers if necessary.  */
00142          for (i = 0; i < tic4x_num_registers; i++)
00143            registertable[tic4x_registers[i].regno] =
00144              (tic4x_register_t *)(tic4x_registers + i);
00145        }
00146     }
00147   if ((int) regno > (IS_CPU_TIC4X (tic4x_version) ? TIC4X_REG_MAX : TIC3X_REG_MAX))
00148     return 0;
00149   if (info != NULL)
00150     (*info->fprintf_func) (info->stream, "%s", registertable[regno]->name);
00151   return 1;
00152 }
00153 
00154 static int
00155 tic4x_print_addr (struct disassemble_info *info, unsigned long addr)
00156 {
00157   if (info != NULL)
00158     (*info->print_address_func)(addr, info);
00159   return 1;
00160 }
00161 
00162 static int
00163 tic4x_print_relative (struct disassemble_info *info,
00164                     unsigned long pc,
00165                     long offset,
00166                     unsigned long opcode)
00167 {
00168   return tic4x_print_addr (info, pc + offset + tic4x_pc_offset (opcode));
00169 }
00170 
00171 static int
00172 tic4x_print_direct (struct disassemble_info *info, unsigned long arg)
00173 {
00174   if (info != NULL)
00175     {
00176       (*info->fprintf_func) (info->stream, "@");
00177       tic4x_print_addr (info, arg + (tic4x_dp << 16));
00178     }
00179   return 1;
00180 }
00181 #if 0
00182 /* FIXME: make the floating point stuff not rely on host
00183    floating point arithmetic.  */
00184 
00185 static void
00186 tic4x_print_ftoa (unsigned int val, FILE *stream, fprintf_ftype pfunc)
00187 {
00188   int e;
00189   int s;
00190   int f;
00191   double num = 0.0;
00192 
00193   e = EXTRS (val, 31, 24);  /* Exponent.  */
00194   if (e != -128)
00195     {
00196       s = EXTRU (val, 23, 23);     /* Sign bit.  */
00197       f = EXTRU (val, 22, 0);      /* Mantissa.  */
00198       if (s)
00199        f += -2 * (1 << 23);
00200       else
00201        f += (1 << 23);
00202       num = f / (double)(1 << 23);
00203       num = ldexp (num, e);
00204     }
00205   (*pfunc)(stream, "%.9g", num);
00206 }
00207 #endif
00208 
00209 static int
00210 tic4x_print_immed (struct disassemble_info *info,
00211                  immed_t type,
00212                  unsigned long arg)
00213 {
00214   int s;
00215   int f;
00216   int e;
00217   double num = 0.0;
00218 
00219   if (info == NULL)
00220     return 1;
00221   switch (type)
00222     {
00223     case IMMED_SINT:
00224     case IMMED_INT:
00225       (*info->fprintf_func) (info->stream, "%ld", (long) arg);
00226       break;
00227 
00228     case IMMED_SUINT:
00229     case IMMED_UINT:
00230       (*info->fprintf_func) (info->stream, "%lu", arg);
00231       break;
00232 
00233     case IMMED_SFLOAT:
00234       e = EXTRS (arg, 15, 12);
00235       if (e != -8)
00236        {
00237          s = EXTRU (arg, 11, 11);
00238          f = EXTRU (arg, 10, 0);
00239          if (s)
00240            f += -2 * (1 << 11);
00241          else
00242            f += (1 << 11);
00243          num = f / (double)(1 << 11);
00244          num = ldexp (num, e);
00245        }
00246       (*info->fprintf_func) (info->stream, "%f", num);
00247       break;
00248     case IMMED_FLOAT:
00249       e = EXTRS (arg, 31, 24);
00250       if (e != -128)
00251        {
00252          s = EXTRU (arg, 23, 23);
00253          f = EXTRU (arg, 22, 0);
00254          if (s)
00255            f += -2 * (1 << 23);
00256          else
00257            f += (1 << 23);
00258          num = f / (double)(1 << 23);
00259          num = ldexp (num, e);
00260        }
00261       (*info->fprintf_func) (info->stream, "%f", num);
00262       break;
00263     }
00264   return 1;
00265 }
00266 
00267 static int
00268 tic4x_print_cond (struct disassemble_info *info, unsigned int cond)
00269 {
00270   static tic4x_cond_t **condtable = NULL;
00271   unsigned int i;
00272 
00273   if (condtable == NULL)
00274     {
00275       condtable = xmalloc (sizeof (tic4x_cond_t *) * 32);
00276       for (i = 0; i < tic4x_num_conds; i++)
00277        condtable[tic4x_conds[i].cond] = (tic4x_cond_t *)(tic4x_conds + i);
00278     }
00279   if (cond > 31 || condtable[cond] == NULL)
00280     return 0;
00281   if (info != NULL)
00282     (*info->fprintf_func) (info->stream, "%s", condtable[cond]->name);
00283   return 1;
00284 }
00285 
00286 static int
00287 tic4x_print_indirect (struct disassemble_info *info,
00288                     indirect_t type,
00289                     unsigned long arg)
00290 {
00291   unsigned int aregno;
00292   unsigned int modn;
00293   unsigned int disp;
00294   char *a;
00295 
00296   aregno = 0;
00297   modn = 0;
00298   disp = 1;
00299   switch(type)
00300     {
00301     case INDIRECT_TIC4X:           /* *+ARn(disp) */
00302       disp = EXTRU (arg, 7, 3);
00303       aregno = EXTRU (arg, 2, 0) + REG_AR0;
00304       modn = 0;
00305       break;
00306     case INDIRECT_SHORT:
00307       disp = 1;
00308       aregno = EXTRU (arg, 2, 0) + REG_AR0;
00309       modn = EXTRU (arg, 7, 3);
00310       break;
00311     case INDIRECT_LONG:
00312       disp = EXTRU (arg, 7, 0);
00313       aregno = EXTRU (arg, 10, 8) + REG_AR0;
00314       modn = EXTRU (arg, 15, 11);
00315       if (modn > 7 && disp != 0)
00316        return 0;
00317       break;
00318     default:
00319         (*info->fprintf_func)(info->stream, "# internal error: Unknown indirect type %d", type);
00320         return 0;
00321     }
00322   if (modn > TIC3X_MODN_MAX)
00323     return 0;
00324   a = tic4x_indirects[modn].name;
00325   while (*a)
00326     {
00327       switch (*a)
00328        {
00329        case 'a':
00330          tic4x_print_register (info, aregno);
00331          break;
00332        case 'd':
00333          tic4x_print_immed (info, IMMED_UINT, disp);
00334          break;
00335        case 'y':
00336          tic4x_print_str (info, "ir0");
00337          break;
00338        case 'z':
00339          tic4x_print_str (info, "ir1");
00340          break;
00341        default:
00342          tic4x_print_char (info, *a);
00343          break;
00344        }
00345       a++;
00346     }
00347   return 1;
00348 }
00349 
00350 static int
00351 tic4x_print_op (struct disassemble_info *info,
00352               unsigned long instruction,
00353               tic4x_inst_t *p,
00354               unsigned long pc)
00355 {
00356   int val;
00357   char *s;
00358   char *parallel = NULL;
00359 
00360   /* Print instruction name.  */
00361   s = p->name;
00362   while (*s && parallel == NULL)
00363     {
00364       switch (*s)
00365        {
00366        case 'B':
00367          if (! tic4x_print_cond (info, EXTRU (instruction, 20, 16)))
00368            return 0;
00369          break;
00370        case 'C':
00371          if (! tic4x_print_cond (info, EXTRU (instruction, 27, 23)))
00372            return 0;
00373          break;
00374        case '_':
00375          parallel = s + 1;  /* Skip past `_' in name.  */
00376          break;
00377        default:
00378          tic4x_print_char (info, *s);
00379          break;
00380        }
00381       s++;
00382     }
00383 
00384   /* Print arguments.  */
00385   s = p->args;
00386   if (*s)
00387     tic4x_print_char (info, ' ');
00388 
00389   while (*s)
00390     {
00391       switch (*s)
00392        {
00393        case '*': /* Indirect 0--15.  */
00394          if (! tic4x_print_indirect (info, INDIRECT_LONG,
00395                                   EXTRU (instruction, 15, 0)))
00396            return 0;
00397          break;
00398 
00399        case '#': /* Only used for ldp, ldpk.  */
00400          tic4x_print_immed (info, IMMED_UINT, EXTRU (instruction, 15, 0));
00401          break;
00402 
00403        case '@': /* Direct 0--15.  */
00404          tic4x_print_direct (info, EXTRU (instruction, 15, 0));
00405          break;
00406 
00407        case 'A': /* Address register 24--22.  */
00408          if (! tic4x_print_register (info, EXTRU (instruction, 24, 22) +
00409                                   REG_AR0))
00410            return 0;
00411          break;
00412 
00413        case 'B': /* 24-bit unsigned int immediate br(d)/call/rptb
00414                    address 0--23.  */
00415          if (IS_CPU_TIC4X (tic4x_version))
00416            tic4x_print_relative (info, pc, EXTRS (instruction, 23, 0),
00417                               p->opcode);
00418          else
00419            tic4x_print_addr (info, EXTRU (instruction, 23, 0));
00420          break;
00421 
00422        case 'C': /* Indirect (short C4x) 0--7.  */
00423          if (! IS_CPU_TIC4X (tic4x_version))
00424            return 0;
00425          if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
00426                                   EXTRU (instruction, 7, 0)))
00427            return 0;
00428          break;
00429 
00430        case 'D':
00431          /* Cockup if get here...  */
00432          break;
00433 
00434        case 'E': /* Register 0--7.  */
00435         case 'e':
00436          if (! tic4x_print_register (info, EXTRU (instruction, 7, 0)))
00437            return 0;
00438          break;
00439 
00440        case 'F': /* 16-bit float immediate 0--15.  */
00441          tic4x_print_immed (info, IMMED_SFLOAT,
00442                           EXTRU (instruction, 15, 0));
00443          break;
00444 
00445         case 'i': /* Extended indirect 0--7.  */
00446           if (EXTRU (instruction, 7, 5) == 7)
00447             {
00448               if (!tic4x_print_register (info, EXTRU (instruction, 4, 0)))
00449                 return 0;
00450               break;
00451             }
00452           /* Fallthrough */
00453 
00454        case 'I': /* Indirect (short) 0--7.  */
00455          if (! tic4x_print_indirect (info, INDIRECT_SHORT,
00456                                   EXTRU (instruction, 7, 0)))
00457            return 0;
00458          break;
00459 
00460         case 'j': /* Extended indirect 8--15 */
00461           if (EXTRU (instruction, 15, 13) == 7)
00462             {
00463               if (! tic4x_print_register (info, EXTRU (instruction, 12, 8)))
00464                 return 0;
00465               break;
00466             }
00467 
00468        case 'J': /* Indirect (short) 8--15.  */
00469          if (! tic4x_print_indirect (info, INDIRECT_SHORT,
00470                                   EXTRU (instruction, 15, 8)))
00471            return 0;
00472          break;
00473 
00474        case 'G': /* Register 8--15.  */
00475         case 'g':
00476          if (! tic4x_print_register (info, EXTRU (instruction, 15, 8)))
00477            return 0;
00478          break;
00479 
00480        case 'H': /* Register 16--18.  */
00481          if (! tic4x_print_register (info, EXTRU (instruction, 18, 16)))
00482            return 0;
00483          break;
00484 
00485        case 'K': /* Register 19--21.  */
00486          if (! tic4x_print_register (info, EXTRU (instruction, 21, 19)))
00487            return 0;
00488          break;
00489 
00490        case 'L': /* Register 22--24.  */
00491          if (! tic4x_print_register (info, EXTRU (instruction, 24, 22)))
00492            return 0;
00493          break;
00494 
00495        case 'M': /* Register 22--22.  */
00496          tic4x_print_register (info, EXTRU (instruction, 22, 22) + REG_R2);
00497          break;
00498 
00499        case 'N': /* Register 23--23.  */
00500          tic4x_print_register (info, EXTRU (instruction, 23, 23) + REG_R0);
00501          break;
00502 
00503        case 'O': /* Indirect (short C4x) 8--15.  */
00504          if (! IS_CPU_TIC4X (tic4x_version))
00505            return 0;
00506          if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
00507                                   EXTRU (instruction, 15, 8)))
00508            return 0;
00509          break;
00510 
00511        case 'P': /* Displacement 0--15 (used by Bcond and BcondD).  */
00512          tic4x_print_relative (info, pc, EXTRS (instruction, 15, 0),
00513                             p->opcode);
00514          break;
00515 
00516        case 'Q': /* Register 0--15.  */
00517         case 'q':
00518          if (! tic4x_print_register (info, EXTRU (instruction, 15, 0)))
00519            return 0;
00520          break;
00521 
00522        case 'R': /* Register 16--20.  */
00523         case 'r':
00524          if (! tic4x_print_register (info, EXTRU (instruction, 20, 16)))
00525            return 0;
00526          break;
00527 
00528        case 'S': /* 16-bit signed immediate 0--15.  */
00529          tic4x_print_immed (info, IMMED_SINT,
00530                           EXTRS (instruction, 15, 0));
00531          break;
00532 
00533        case 'T': /* 5-bit signed immediate 16--20  (C4x stik).  */
00534          if (! IS_CPU_TIC4X (tic4x_version))
00535            return 0;
00536          if (! tic4x_print_immed (info, IMMED_SUINT,
00537                                EXTRU (instruction, 20, 16)))
00538            return 0;
00539          break;
00540 
00541        case 'U': /* 16-bit unsigned int immediate 0--15.  */
00542          tic4x_print_immed (info, IMMED_SUINT, EXTRU (instruction, 15, 0));
00543          break;
00544 
00545        case 'V': /* 5/9-bit unsigned vector 0--4/8.  */
00546          tic4x_print_immed (info, IMMED_SUINT,
00547                           IS_CPU_TIC4X (tic4x_version) ?
00548                           EXTRU (instruction, 8, 0) :
00549                           EXTRU (instruction, 4, 0) & ~0x20);
00550          break;
00551 
00552        case 'W': /* 8-bit signed immediate 0--7.  */
00553          if (! IS_CPU_TIC4X (tic4x_version))
00554            return 0;
00555          tic4x_print_immed (info, IMMED_SINT, EXTRS (instruction, 7, 0));
00556          break;
00557 
00558        case 'X': /* Expansion register 4--0.  */
00559          val = EXTRU (instruction, 4, 0) + REG_IVTP;
00560          if (val < REG_IVTP || val > REG_TVTP)
00561            return 0;
00562          if (! tic4x_print_register (info, val))
00563            return 0;
00564          break;
00565 
00566        case 'Y': /* Address register 16--20.  */
00567          val = EXTRU (instruction, 20, 16);
00568          if (val < REG_AR0 || val > REG_SP)
00569            return 0;
00570          if (! tic4x_print_register (info, val))
00571            return 0;
00572          break;
00573 
00574        case 'Z': /* Expansion register 16--20.  */
00575          val = EXTRU (instruction, 20, 16) + REG_IVTP;
00576          if (val < REG_IVTP || val > REG_TVTP)
00577            return 0;
00578          if (! tic4x_print_register (info, val))
00579            return 0;
00580          break;
00581 
00582        case '|':     /* Parallel instruction.  */
00583          tic4x_print_str (info, " || ");
00584          tic4x_print_str (info, parallel);
00585          tic4x_print_char (info, ' ');
00586          break;
00587 
00588        case ';':
00589          tic4x_print_char (info, ',');
00590          break;
00591 
00592        default:
00593          tic4x_print_char (info, *s);
00594          break;
00595        }
00596       s++;
00597     }
00598   return 1;
00599 }
00600 
00601 static void
00602 tic4x_hash_opcode_special (tic4x_inst_t **optable_special,
00603                         const tic4x_inst_t *inst)
00604 {
00605   int i;
00606 
00607   for (i = 0;i < TIC4X_SPESOP_SIZE; i++)
00608     if (optable_special[i] != NULL
00609         && optable_special[i]->opcode == inst->opcode)
00610       {
00611         /* Collision (we have it already) - overwrite.  */
00612         optable_special[i] = (tic4x_inst_t *) inst;
00613         return;
00614       }
00615 
00616   for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
00617     if (optable_special[i] == NULL)
00618       {
00619         /* Add the new opcode.  */
00620         optable_special[i] = (tic4x_inst_t *) inst;
00621         return;
00622       }
00623 
00624   /* This should never occur. This happens if the number of special
00625      instructions exceeds TIC4X_SPESOP_SIZE. Please increase the variable
00626      of this variable */
00627 #if TIC4X_DEBUG
00628   printf ("optable_special[] is full, please increase TIC4X_SPESOP_SIZE!\n");
00629 #endif
00630 }
00631 
00632 static void
00633 tic4x_hash_opcode (tic4x_inst_t **optable,
00634                  tic4x_inst_t **optable_special,
00635                  const tic4x_inst_t *inst,
00636                  const unsigned long tic4x_oplevel)
00637 {
00638   int j;
00639   int opcode = inst->opcode >> (32 - TIC4X_HASH_SIZE);
00640   int opmask = inst->opmask >> (32 - TIC4X_HASH_SIZE);
00641 
00642   /* Use a TIC4X_HASH_SIZE bit index as a hash index.  We should
00643      have unique entries so there's no point having a linked list
00644      for each entry?  */
00645   for (j = opcode; j < opmask; j++)
00646     if ((j & opmask) == opcode
00647          && inst->oplevel & tic4x_oplevel)
00648       {
00649 #if TIC4X_DEBUG
00650        /* We should only have collisions for synonyms like
00651           ldp for ldi.  */
00652        if (optable[j] != NULL)
00653          printf ("Collision at index %d, %s and %s\n",
00654                 j, optable[j]->name, inst->name);
00655 #endif
00656         /* Catch those ops that collide with others already inside the
00657            hash, and have a opmask greater than the one we use in the
00658            hash. Store them in a special-list, that will handle full
00659            32-bit INSN, not only the first 11-bit (or so). */
00660         if (optable[j] != NULL
00661            && inst->opmask & ~(opmask << (32 - TIC4X_HASH_SIZE)))
00662           {
00663             /* Add the instruction already on the list.  */
00664             tic4x_hash_opcode_special (optable_special, optable[j]);
00665 
00666             /* Add the new instruction.  */
00667             tic4x_hash_opcode_special (optable_special, inst);
00668           }
00669 
00670         optable[j] = (tic4x_inst_t *) inst;
00671       }
00672 }
00673 
00674 /* Disassemble the instruction in 'instruction'.
00675    'pc' should be the address of this instruction, it will
00676    be used to print the target address if this is a relative jump or call
00677    the disassembled instruction is written to 'info'.
00678    The function returns the length of this instruction in words.  */
00679 
00680 static int
00681 tic4x_disassemble (unsigned long pc,
00682                  unsigned long instruction,
00683                  struct disassemble_info *info)
00684 {
00685   static tic4x_inst_t **optable = NULL;
00686   static tic4x_inst_t **optable_special = NULL;
00687   tic4x_inst_t *p;
00688   int i;
00689   unsigned long tic4x_oplevel;
00690 
00691   tic4x_version = info->mach;
00692 
00693   tic4x_oplevel  = (IS_CPU_TIC4X (tic4x_version)) ? OP_C4X : 0;
00694   tic4x_oplevel |= OP_C3X | OP_LPWR | OP_IDLE2 | OP_ENH;
00695 
00696   if (optable == NULL)
00697     {
00698       optable = xcalloc (sizeof (tic4x_inst_t *), (1 << TIC4X_HASH_SIZE));
00699 
00700       optable_special = xcalloc (sizeof (tic4x_inst_t *), TIC4X_SPESOP_SIZE);
00701 
00702       /* Install opcodes in reverse order so that preferred
00703         forms overwrite synonyms.  */
00704       for (i = tic4x_num_insts - 1; i >= 0; i--)
00705         tic4x_hash_opcode (optable, optable_special, &tic4x_insts[i],
00706                         tic4x_oplevel);
00707 
00708       /* We now need to remove the insn that are special from the
00709          "normal" optable, to make the disasm search this extra list
00710          for them.  */
00711       for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
00712         if (optable_special[i] != NULL)
00713           optable[optable_special[i]->opcode >> (32 - TIC4X_HASH_SIZE)] = NULL;
00714     }
00715 
00716   /* See if we can pick up any loading of the DP register...  */
00717   if ((instruction >> 16) == 0x5070 || (instruction >> 16) == 0x1f70)
00718     tic4x_dp = EXTRU (instruction, 15, 0);
00719 
00720   p = optable[instruction >> (32 - TIC4X_HASH_SIZE)];
00721   if (p != NULL)
00722     {
00723       if (((instruction & p->opmask) == p->opcode)
00724            && tic4x_print_op (NULL, instruction, p, pc))
00725         tic4x_print_op (info, instruction, p, pc);
00726       else
00727         (*info->fprintf_func) (info->stream, "%08lx", instruction);
00728     }
00729   else
00730     {
00731       for (i = 0; i<TIC4X_SPESOP_SIZE; i++)
00732         if (optable_special[i] != NULL
00733             && optable_special[i]->opcode == instruction)
00734           {
00735             (*info->fprintf_func)(info->stream, "%s", optable_special[i]->name);
00736             break;
00737           }
00738       if (i == TIC4X_SPESOP_SIZE)
00739         (*info->fprintf_func) (info->stream, "%08lx", instruction);
00740     }
00741 
00742   /* Return size of insn in words.  */
00743   return 1;
00744 }
00745 
00746 /* The entry point from objdump and gdb.  */
00747 int
00748 print_insn_tic4x (bfd_vma memaddr, struct disassemble_info *info)
00749 {
00750   int status;
00751   unsigned long pc;
00752   unsigned long op;
00753   bfd_byte buffer[4];
00754 
00755   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
00756   if (status != 0)
00757     {
00758       (*info->memory_error_func) (status, memaddr, info);
00759       return -1;
00760     }
00761 
00762   pc = memaddr;
00763   op = bfd_getl32 (buffer);
00764   info->bytes_per_line = 4;
00765   info->bytes_per_chunk = 4;
00766   info->octets_per_byte = 4;
00767   info->display_endian = BFD_ENDIAN_LITTLE;
00768   return tic4x_disassemble (pc, op, info) * 4;
00769 }