(root)/
binutils-2.41/
opcodes/
tic4x-dis.c
       1  /* Print instructions for the Texas TMS320C[34]X, for GDB and GNU Binutils.
       2  
       3     Copyright (C) 2002-2023 Free Software Foundation, Inc.
       4  
       5     Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
       6  
       7     This file is part of the GNU opcodes library.
       8  
       9     This library is free software; you can redistribute it and/or modify
      10     it under the terms of the GNU General Public License as published by
      11     the Free Software Foundation; either version 3, or (at your option)
      12     any later version.
      13  
      14     It is distributed in the hope that it will be useful, but WITHOUT
      15     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      16     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      17     License for more details.
      18  
      19     You should have received a copy of the GNU General Public License
      20     along with this program; if not, write to the Free Software
      21     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      22     MA 02110-1301, USA.  */
      23  
      24  #include "sysdep.h"
      25  #include <math.h>
      26  #include "libiberty.h"
      27  #include "disassemble.h"
      28  #include "opcode/tic4x.h"
      29  
      30  #define TIC4X_DEBUG 0
      31  
      32  #define TIC4X_HASH_SIZE   11   /* 11 (bits) and above should give unique entries.  */
      33  #define TIC4X_SPESOP_SIZE 8    /* Max 8. ops for special instructions.  */
      34  
      35  typedef enum
      36  {
      37    IMMED_SINT,
      38    IMMED_SUINT,
      39    IMMED_SFLOAT,
      40    IMMED_INT,
      41    IMMED_UINT,
      42    IMMED_FLOAT
      43  }
      44  immed_t;
      45  
      46  typedef enum
      47  {
      48    INDIRECT_SHORT,
      49    INDIRECT_LONG,
      50    INDIRECT_TIC4X
      51  }
      52  indirect_t;
      53  
      54  static unsigned long tic4x_version = 0;
      55  static unsigned int tic4x_dp = 0;
      56  static tic4x_inst_t **optab = NULL;
      57  static tic4x_inst_t **optab_special = NULL;
      58  static const char *registernames[REG_TABLE_SIZE];
      59  
      60  static int
      61  tic4x_pc_offset (unsigned int op)
      62  {
      63    /* Determine the PC offset for a C[34]x instruction.
      64       This could be simplified using some boolean algebra
      65       but at the expense of readability.  */
      66    switch (op >> 24)
      67      {
      68      case 0x60:	/* br */
      69      case 0x62:	/* call  (C4x) */
      70      case 0x64:	/* rptb  (C4x) */
      71        return 1;
      72      case 0x61: 	/* brd */
      73      case 0x63: 	/* laj */
      74      case 0x65:	/* rptbd (C4x) */
      75        return 3;
      76      case 0x66: 	/* swi */
      77      case 0x67:
      78        return 0;
      79      default:
      80        break;
      81      }
      82  
      83    switch ((op & 0xffe00000) >> 20)
      84      {
      85      case 0x6a0:	/* bB */
      86      case 0x720: /* callB */
      87      case 0x740: /* trapB */
      88        return 1;
      89  
      90      case 0x6a2: /* bBd */
      91      case 0x6a6: /* bBat */
      92      case 0x6aa: /* bBaf */
      93      case 0x722:	/* lajB */
      94      case 0x748: /* latB */
      95      case 0x798: /* rptbd */
      96        return 3;
      97  
      98      default:
      99        break;
     100      }
     101  
     102    switch ((op & 0xfe200000) >> 20)
     103      {
     104      case 0x6e0:	/* dbB */
     105        return 1;
     106  
     107      case 0x6e2:	/* dbBd */
     108        return 3;
     109  
     110      default:
     111        break;
     112      }
     113  
     114    return 0;
     115  }
     116  
     117  static int
     118  tic4x_print_char (struct disassemble_info * info, char ch)
     119  {
     120    if (info != NULL)
     121      (*info->fprintf_func) (info->stream, "%c", ch);
     122    return 1;
     123  }
     124  
     125  static int
     126  tic4x_print_str (struct disassemble_info *info, const char *str)
     127  {
     128    if (info != NULL)
     129      (*info->fprintf_func) (info->stream, "%s", str);
     130    return 1;
     131  }
     132  
     133  static int
     134  tic4x_print_register (struct disassemble_info *info, unsigned long regno)
     135  {
     136    unsigned int i;
     137  
     138    if (registernames[REG_R0] == NULL)
     139      {
     140        for (i = 0; i < tic3x_num_registers; i++)
     141  	registernames[tic3x_registers[i].regno] = tic3x_registers[i].name;
     142        if (IS_CPU_TIC4X (tic4x_version))
     143  	{
     144  	  /* Add C4x additional registers, overwriting
     145  	     any C3x registers if necessary.  */
     146  	  for (i = 0; i < tic4x_num_registers; i++)
     147  	    registernames[tic4x_registers[i].regno] = tic4x_registers[i].name;
     148  	}
     149      }
     150    if (regno > (IS_CPU_TIC4X (tic4x_version) ? TIC4X_REG_MAX : TIC3X_REG_MAX))
     151      return 0;
     152    if (info != NULL)
     153      (*info->fprintf_func) (info->stream, "%s", registernames[regno]);
     154    return 1;
     155  }
     156  
     157  static int
     158  tic4x_print_addr (struct disassemble_info *info, unsigned long addr)
     159  {
     160    if (info != NULL)
     161      (*info->print_address_func)(addr, info);
     162    return 1;
     163  }
     164  
     165  static int
     166  tic4x_print_relative (struct disassemble_info *info,
     167  		      unsigned long pc,
     168  		      long offset,
     169  		      unsigned long opcode)
     170  {
     171    return tic4x_print_addr (info, pc + offset + tic4x_pc_offset (opcode));
     172  }
     173  
     174  static int
     175  tic4x_print_direct (struct disassemble_info *info, unsigned long arg)
     176  {
     177    if (info != NULL)
     178      {
     179        (*info->fprintf_func) (info->stream, "@");
     180        tic4x_print_addr (info, arg + (tic4x_dp << 16));
     181      }
     182    return 1;
     183  }
     184  #if 0
     185  /* FIXME: make the floating point stuff not rely on host
     186     floating point arithmetic.  */
     187  
     188  static void
     189  tic4x_print_ftoa (unsigned int val, FILE *stream, fprintf_ftype pfunc)
     190  {
     191    int e;
     192    int s;
     193    int f;
     194    double num = 0.0;
     195  
     196    e = EXTRS (val, 31, 24);	/* Exponent.  */
     197    if (e != -128)
     198      {
     199        s = EXTRU (val, 23, 23);	/* Sign bit.  */
     200        f = EXTRU (val, 22, 0);	/* Mantissa.  */
     201        if (s)
     202  	f += -2 * (1 << 23);
     203        else
     204  	f += (1 << 23);
     205        num = f / (double)(1 << 23);
     206        num = ldexp (num, e);
     207      }
     208    (*pfunc)(stream, "%.9g", num);
     209  }
     210  #endif
     211  
     212  static int
     213  tic4x_print_immed (struct disassemble_info *info,
     214  		   immed_t type,
     215  		   unsigned long arg)
     216  {
     217    int s;
     218    int f;
     219    int e;
     220    double num = 0.0;
     221  
     222    if (info == NULL)
     223      return 1;
     224    switch (type)
     225      {
     226      case IMMED_SINT:
     227      case IMMED_INT:
     228        (*info->fprintf_func) (info->stream, "%ld", (long) arg);
     229        break;
     230  
     231      case IMMED_SUINT:
     232      case IMMED_UINT:
     233        (*info->fprintf_func) (info->stream, "%lu", arg);
     234        break;
     235  
     236      case IMMED_SFLOAT:
     237        e = EXTRS (arg, 15, 12);
     238        if (e != -8)
     239  	{
     240  	  s = EXTRU (arg, 11, 11);
     241  	  f = EXTRU (arg, 10, 0);
     242  	  if (s)
     243  	    f += -2 * (1 << 11);
     244  	  else
     245  	    f += (1 << 11);
     246  	  num = f / (double)(1 << 11);
     247  	  num = ldexp (num, e);
     248  	}
     249        (*info->fprintf_func) (info->stream, "%f", num);
     250        break;
     251      case IMMED_FLOAT:
     252        e = EXTRS (arg, 31, 24);
     253        if (e != -128)
     254  	{
     255  	  s = EXTRU (arg, 23, 23);
     256  	  f = EXTRU (arg, 22, 0);
     257  	  if (s)
     258  	    f += -2 * (1 << 23);
     259  	  else
     260  	    f += (1 << 23);
     261  	  num = f / (double)(1 << 23);
     262  	  num = ldexp (num, e);
     263  	}
     264        (*info->fprintf_func) (info->stream, "%f", num);
     265        break;
     266      }
     267    return 1;
     268  }
     269  
     270  static int
     271  tic4x_print_cond (struct disassemble_info *info, unsigned int cond)
     272  {
     273    static tic4x_cond_t **condtable = NULL;
     274    unsigned int i;
     275  
     276    if (condtable == NULL)
     277      {
     278        condtable = xcalloc (32, sizeof (tic4x_cond_t *));
     279        for (i = 0; i < tic4x_num_conds; i++)
     280  	condtable[tic4x_conds[i].cond] = (tic4x_cond_t *)(tic4x_conds + i);
     281      }
     282    if (cond > 31 || condtable[cond] == NULL)
     283      return 0;
     284    if (info != NULL)
     285      (*info->fprintf_func) (info->stream, "%s", condtable[cond]->name);
     286    return 1;
     287  }
     288  
     289  static int
     290  tic4x_print_indirect (struct disassemble_info *info,
     291  		      indirect_t type,
     292  		      unsigned long arg)
     293  {
     294    unsigned int aregno;
     295    unsigned int modn;
     296    unsigned int disp;
     297    const char *a;
     298  
     299    aregno = 0;
     300    modn = 0;
     301    disp = 1;
     302    switch(type)
     303      {
     304      case INDIRECT_TIC4X:		/* *+ARn(disp) */
     305        disp = EXTRU (arg, 7, 3);
     306        aregno = EXTRU (arg, 2, 0) + REG_AR0;
     307        modn = 0;
     308        break;
     309      case INDIRECT_SHORT:
     310        disp = 1;
     311        aregno = EXTRU (arg, 2, 0) + REG_AR0;
     312        modn = EXTRU (arg, 7, 3);
     313        break;
     314      case INDIRECT_LONG:
     315        disp = EXTRU (arg, 7, 0);
     316        aregno = EXTRU (arg, 10, 8) + REG_AR0;
     317        modn = EXTRU (arg, 15, 11);
     318        if (modn > 7 && disp != 0)
     319  	return 0;
     320        break;
     321      default:
     322          (*info->fprintf_func)(info->stream, "# internal error: Unknown indirect type %d", type);
     323          return 0;
     324      }
     325    if (modn > TIC3X_MODN_MAX)
     326      return 0;
     327    a = tic4x_indirects[modn].name;
     328    while (*a)
     329      {
     330        switch (*a)
     331  	{
     332  	case 'a':
     333  	  tic4x_print_register (info, aregno);
     334  	  break;
     335  	case 'd':
     336  	  tic4x_print_immed (info, IMMED_UINT, disp);
     337  	  break;
     338  	case 'y':
     339  	  tic4x_print_str (info, "ir0");
     340  	  break;
     341  	case 'z':
     342  	  tic4x_print_str (info, "ir1");
     343  	  break;
     344  	default:
     345  	  tic4x_print_char (info, *a);
     346  	  break;
     347  	}
     348        a++;
     349      }
     350    return 1;
     351  }
     352  
     353  static int
     354  tic4x_print_op (struct disassemble_info *info,
     355  		unsigned long instruction,
     356  		tic4x_inst_t *p,
     357  		unsigned long pc)
     358  {
     359    int val;
     360    const char *s;
     361    const char *parallel = NULL;
     362  
     363    /* Print instruction name.  */
     364    s = p->name;
     365    while (*s && parallel == NULL)
     366      {
     367        switch (*s)
     368  	{
     369  	case 'B':
     370  	  if (! tic4x_print_cond (info, EXTRU (instruction, 20, 16)))
     371  	    return 0;
     372  	  break;
     373  	case 'C':
     374  	  if (! tic4x_print_cond (info, EXTRU (instruction, 27, 23)))
     375  	    return 0;
     376  	  break;
     377  	case '_':
     378  	  parallel = s + 1;	/* Skip past `_' in name.  */
     379  	  break;
     380  	default:
     381  	  tic4x_print_char (info, *s);
     382  	  break;
     383  	}
     384        s++;
     385      }
     386  
     387    /* Print arguments.  */
     388    s = p->args;
     389    if (*s)
     390      tic4x_print_char (info, ' ');
     391  
     392    while (*s)
     393      {
     394        switch (*s)
     395  	{
     396  	case '*': /* Indirect 0--15.  */
     397  	  if (! tic4x_print_indirect (info, INDIRECT_LONG,
     398  				      EXTRU (instruction, 15, 0)))
     399  	    return 0;
     400  	  break;
     401  
     402  	case '#': /* Only used for ldp, ldpk.  */
     403  	  tic4x_print_immed (info, IMMED_UINT, EXTRU (instruction, 15, 0));
     404  	  break;
     405  
     406  	case '@': /* Direct 0--15.  */
     407  	  tic4x_print_direct (info, EXTRU (instruction, 15, 0));
     408  	  break;
     409  
     410  	case 'A': /* Address register 24--22.  */
     411  	  if (! tic4x_print_register (info, EXTRU (instruction, 24, 22) +
     412  				      REG_AR0))
     413  	    return 0;
     414  	  break;
     415  
     416  	case 'B': /* 24-bit unsigned int immediate br(d)/call/rptb
     417  		     address 0--23.  */
     418  	  if (IS_CPU_TIC4X (tic4x_version))
     419  	    tic4x_print_relative (info, pc, EXTRS (instruction, 23, 0),
     420  				  p->opcode);
     421  	  else
     422  	    tic4x_print_addr (info, EXTRU (instruction, 23, 0));
     423  	  break;
     424  
     425  	case 'C': /* Indirect (short C4x) 0--7.  */
     426  	  if (! IS_CPU_TIC4X (tic4x_version))
     427  	    return 0;
     428  	  if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
     429  				      EXTRU (instruction, 7, 0)))
     430  	    return 0;
     431  	  break;
     432  
     433  	case 'D':
     434  	  /* Cockup if get here...  */
     435  	  break;
     436  
     437  	case 'E': /* Register 0--7.  */
     438          case 'e':
     439  	  if (! tic4x_print_register (info, EXTRU (instruction, 7, 0)))
     440  	    return 0;
     441  	  break;
     442  
     443  	case 'F': /* 16-bit float immediate 0--15.  */
     444  	  tic4x_print_immed (info, IMMED_SFLOAT,
     445  			     EXTRU (instruction, 15, 0));
     446  	  break;
     447  
     448          case 'i': /* Extended indirect 0--7.  */
     449            if (EXTRU (instruction, 7, 5) == 7)
     450              {
     451                if (!tic4x_print_register (info, EXTRU (instruction, 4, 0)))
     452                  return 0;
     453                break;
     454              }
     455            /* Fallthrough */
     456  
     457  	case 'I': /* Indirect (short) 0--7.  */
     458  	  if (! tic4x_print_indirect (info, INDIRECT_SHORT,
     459  				      EXTRU (instruction, 7, 0)))
     460  	    return 0;
     461  	  break;
     462  
     463          case 'j': /* Extended indirect 8--15 */
     464            if (EXTRU (instruction, 15, 13) == 7)
     465              {
     466                if (! tic4x_print_register (info, EXTRU (instruction, 12, 8)))
     467                  return 0;
     468                break;
     469              }
     470  	  /* Fall through.  */
     471  
     472  	case 'J': /* Indirect (short) 8--15.  */
     473  	  if (! tic4x_print_indirect (info, INDIRECT_SHORT,
     474  				      EXTRU (instruction, 15, 8)))
     475  	    return 0;
     476  	  break;
     477  
     478  	case 'G': /* Register 8--15.  */
     479          case 'g':
     480  	  if (! tic4x_print_register (info, EXTRU (instruction, 15, 8)))
     481  	    return 0;
     482  	  break;
     483  
     484  	case 'H': /* Register 16--18.  */
     485  	  if (! tic4x_print_register (info, EXTRU (instruction, 18, 16)))
     486  	    return 0;
     487  	  break;
     488  
     489  	case 'K': /* Register 19--21.  */
     490  	  if (! tic4x_print_register (info, EXTRU (instruction, 21, 19)))
     491  	    return 0;
     492  	  break;
     493  
     494  	case 'L': /* Register 22--24.  */
     495  	  if (! tic4x_print_register (info, EXTRU (instruction, 24, 22)))
     496  	    return 0;
     497  	  break;
     498  
     499  	case 'M': /* Register 22--22.  */
     500  	  tic4x_print_register (info, EXTRU (instruction, 22, 22) + REG_R2);
     501  	  break;
     502  
     503  	case 'N': /* Register 23--23.  */
     504  	  tic4x_print_register (info, EXTRU (instruction, 23, 23) + REG_R0);
     505  	  break;
     506  
     507  	case 'O': /* Indirect (short C4x) 8--15.  */
     508  	  if (! IS_CPU_TIC4X (tic4x_version))
     509  	    return 0;
     510  	  if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
     511  				      EXTRU (instruction, 15, 8)))
     512  	    return 0;
     513  	  break;
     514  
     515  	case 'P': /* Displacement 0--15 (used by Bcond and BcondD).  */
     516  	  tic4x_print_relative (info, pc, EXTRS (instruction, 15, 0),
     517  				p->opcode);
     518  	  break;
     519  
     520  	case 'Q': /* Register 0--15.  */
     521          case 'q':
     522  	  if (! tic4x_print_register (info, EXTRU (instruction, 15, 0)))
     523  	    return 0;
     524  	  break;
     525  
     526  	case 'R': /* Register 16--20.  */
     527          case 'r':
     528  	  if (! tic4x_print_register (info, EXTRU (instruction, 20, 16)))
     529  	    return 0;
     530  	  break;
     531  
     532  	case 'S': /* 16-bit signed immediate 0--15.  */
     533  	  tic4x_print_immed (info, IMMED_SINT,
     534  			     EXTRS (instruction, 15, 0));
     535  	  break;
     536  
     537  	case 'T': /* 5-bit signed immediate 16--20  (C4x stik).  */
     538  	  if (! IS_CPU_TIC4X (tic4x_version))
     539  	    return 0;
     540  	  if (! tic4x_print_immed (info, IMMED_SUINT,
     541  				   EXTRU (instruction, 20, 16)))
     542  	    return 0;
     543  	  break;
     544  
     545  	case 'U': /* 16-bit unsigned int immediate 0--15.  */
     546  	  tic4x_print_immed (info, IMMED_SUINT, EXTRU (instruction, 15, 0));
     547  	  break;
     548  
     549  	case 'V': /* 5/9-bit unsigned vector 0--4/8.  */
     550  	  tic4x_print_immed (info, IMMED_SUINT,
     551  			     IS_CPU_TIC4X (tic4x_version) ?
     552  			     EXTRU (instruction, 8, 0) :
     553  			     EXTRU (instruction, 4, 0) & ~0x20);
     554  	  break;
     555  
     556  	case 'W': /* 8-bit signed immediate 0--7.  */
     557  	  if (! IS_CPU_TIC4X (tic4x_version))
     558  	    return 0;
     559  	  tic4x_print_immed (info, IMMED_SINT, EXTRS (instruction, 7, 0));
     560  	  break;
     561  
     562  	case 'X': /* Expansion register 4--0.  */
     563  	  val = EXTRU (instruction, 4, 0) + REG_IVTP;
     564  	  if (val < REG_IVTP || val > REG_TVTP)
     565  	    return 0;
     566  	  if (! tic4x_print_register (info, val))
     567  	    return 0;
     568  	  break;
     569  
     570  	case 'Y': /* Address register 16--20.  */
     571  	  val = EXTRU (instruction, 20, 16);
     572  	  if (val < REG_AR0 || val > REG_SP)
     573  	    return 0;
     574  	  if (! tic4x_print_register (info, val))
     575  	    return 0;
     576  	  break;
     577  
     578  	case 'Z': /* Expansion register 16--20.  */
     579  	  val = EXTRU (instruction, 20, 16) + REG_IVTP;
     580  	  if (val < REG_IVTP || val > REG_TVTP)
     581  	    return 0;
     582  	  if (! tic4x_print_register (info, val))
     583  	    return 0;
     584  	  break;
     585  
     586  	case '|':	/* Parallel instruction.  */
     587  	  tic4x_print_str (info, " || ");
     588  	  tic4x_print_str (info, parallel);
     589  	  tic4x_print_char (info, ' ');
     590  	  break;
     591  
     592  	case ';':
     593  	  tic4x_print_char (info, ',');
     594  	  break;
     595  
     596  	default:
     597  	  tic4x_print_char (info, *s);
     598  	  break;
     599  	}
     600        s++;
     601      }
     602    return 1;
     603  }
     604  
     605  static void
     606  tic4x_hash_opcode_special (tic4x_inst_t **optable_special,
     607  			   const tic4x_inst_t *inst)
     608  {
     609    int i;
     610  
     611    for (i = 0;i < TIC4X_SPESOP_SIZE; i++)
     612      if (optable_special[i] != NULL
     613          && optable_special[i]->opcode == inst->opcode)
     614        {
     615          /* Collision (we have it already) - overwrite.  */
     616          optable_special[i] = (tic4x_inst_t *) inst;
     617          return;
     618        }
     619  
     620    for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
     621      if (optable_special[i] == NULL)
     622        {
     623          /* Add the new opcode.  */
     624          optable_special[i] = (tic4x_inst_t *) inst;
     625          return;
     626        }
     627  
     628    /* This should never occur. This happens if the number of special
     629       instructions exceeds TIC4X_SPESOP_SIZE. Please increase the variable
     630       of this variable */
     631  #if TIC4X_DEBUG
     632    printf ("optable_special[] is full, please increase TIC4X_SPESOP_SIZE!\n");
     633  #endif
     634  }
     635  
     636  static void
     637  tic4x_hash_opcode (tic4x_inst_t **optable,
     638  		   tic4x_inst_t **optable_special,
     639  		   const tic4x_inst_t *inst,
     640  		   const unsigned long tic4x_oplevel)
     641  {
     642    unsigned int j;
     643    unsigned int opcode = inst->opcode >> (32 - TIC4X_HASH_SIZE);
     644    unsigned int opmask = inst->opmask >> (32 - TIC4X_HASH_SIZE);
     645  
     646    /* Use a TIC4X_HASH_SIZE bit index as a hash index.  We should
     647       have unique entries so there's no point having a linked list
     648       for each entry?  */
     649    for (j = opcode; j < opmask; j++)
     650      if ((j & opmask) == opcode
     651           && inst->oplevel & tic4x_oplevel)
     652        {
     653  #if TIC4X_DEBUG
     654  	/* We should only have collisions for synonyms like
     655  	   ldp for ldi.  */
     656  	if (optable[j] != NULL)
     657  	  printf ("Collision at index %d, %s and %s\n",
     658  		  j, optable[j]->name, inst->name);
     659  #endif
     660          /* Catch those ops that collide with others already inside the
     661             hash, and have a opmask greater than the one we use in the
     662             hash. Store them in a special-list, that will handle full
     663             32-bit INSN, not only the first 11-bit (or so). */
     664          if (optable[j] != NULL
     665  	    && inst->opmask & ~(opmask << (32 - TIC4X_HASH_SIZE)))
     666            {
     667              /* Add the instruction already on the list.  */
     668              tic4x_hash_opcode_special (optable_special, optable[j]);
     669  
     670              /* Add the new instruction.  */
     671              tic4x_hash_opcode_special (optable_special, inst);
     672            }
     673  
     674          optable[j] = (tic4x_inst_t *) inst;
     675        }
     676  }
     677  
     678  /* Disassemble the instruction in 'instruction'.
     679     'pc' should be the address of this instruction, it will
     680     be used to print the target address if this is a relative jump or call
     681     the disassembled instruction is written to 'info'.
     682     The function returns the length of this instruction in words.  */
     683  
     684  static int
     685  tic4x_disassemble (unsigned long pc,
     686  		   unsigned long instruction,
     687  		   struct disassemble_info *info)
     688  {
     689    tic4x_inst_t *p;
     690    int i;
     691    unsigned long tic4x_oplevel;
     692  
     693    if (tic4x_version != info->mach)
     694      {
     695        tic4x_version = info->mach;
     696        /* Don't stash anything from a previous call using a different
     697  	 machine.  */
     698        free (optab);
     699        optab = NULL;
     700        free (optab_special);
     701        optab_special = NULL;
     702        registernames[REG_R0] = NULL;
     703      }
     704  
     705    tic4x_oplevel  = (IS_CPU_TIC4X (tic4x_version)) ? OP_C4X : 0;
     706    tic4x_oplevel |= OP_C3X | OP_LPWR | OP_IDLE2 | OP_ENH;
     707  
     708    if (optab == NULL)
     709      {
     710        optab = xcalloc (sizeof (tic4x_inst_t *), (1 << TIC4X_HASH_SIZE));
     711  
     712        optab_special = xcalloc (sizeof (tic4x_inst_t *), TIC4X_SPESOP_SIZE);
     713  
     714        /* Install opcodes in reverse order so that preferred
     715  	 forms overwrite synonyms.  */
     716        for (i = tic4x_num_insts - 1; i >= 0; i--)
     717  	tic4x_hash_opcode (optab, optab_special, &tic4x_insts[i],
     718  			   tic4x_oplevel);
     719  
     720        /* We now need to remove the insn that are special from the
     721  	 "normal" optable, to make the disasm search this extra list
     722  	 for them.  */
     723        for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
     724  	if (optab_special[i] != NULL)
     725  	  optab[optab_special[i]->opcode >> (32 - TIC4X_HASH_SIZE)] = NULL;
     726      }
     727  
     728    /* See if we can pick up any loading of the DP register...  */
     729    if ((instruction >> 16) == 0x5070 || (instruction >> 16) == 0x1f70)
     730      tic4x_dp = EXTRU (instruction, 15, 0);
     731  
     732    p = optab[instruction >> (32 - TIC4X_HASH_SIZE)];
     733    if (p != NULL)
     734      {
     735        if (((instruction & p->opmask) == p->opcode)
     736  	  && tic4x_print_op (NULL, instruction, p, pc))
     737  	tic4x_print_op (info, instruction, p, pc);
     738        else
     739  	(*info->fprintf_func) (info->stream, "%08lx", instruction);
     740      }
     741    else
     742      {
     743        for (i = 0; i<TIC4X_SPESOP_SIZE; i++)
     744  	if (optab_special[i] != NULL
     745  	    && optab_special[i]->opcode == instruction)
     746  	  {
     747  	    (*info->fprintf_func)(info->stream, "%s", optab_special[i]->name);
     748  	    break;
     749  	  }
     750        if (i == TIC4X_SPESOP_SIZE)
     751  	(*info->fprintf_func) (info->stream, "%08lx", instruction);
     752      }
     753  
     754    /* Return size of insn in words.  */
     755    return 1;
     756  }
     757  
     758  /* The entry point from objdump and gdb.  */
     759  int
     760  print_insn_tic4x (bfd_vma memaddr, struct disassemble_info *info)
     761  {
     762    int status;
     763    unsigned long pc;
     764    unsigned long op;
     765    bfd_byte buffer[4];
     766  
     767    status = (*info->read_memory_func) (memaddr, buffer, 4, info);
     768    if (status != 0)
     769      {
     770        (*info->memory_error_func) (status, memaddr, info);
     771        return -1;
     772      }
     773  
     774    pc = memaddr;
     775    op = bfd_getl32 (buffer);
     776    info->bytes_per_line = 4;
     777    info->bytes_per_chunk = 4;
     778    info->octets_per_byte = 4;
     779    info->display_endian = BFD_ENDIAN_LITTLE;
     780    return tic4x_disassemble (pc, op, info) * 4;
     781  }