(root)/
binutils-2.41/
opcodes/
tic30-dis.c
       1  /* Disassembly routines for TMS320C30 architecture
       2     Copyright (C) 1998-2023 Free Software Foundation, Inc.
       3     Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
       4  
       5     This file is part of the GNU opcodes library.
       6  
       7     This library is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3, or (at your option)
      10     any later version.
      11  
      12     It is distributed in the hope that it will be useful, but WITHOUT
      13     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      14     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      15     License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with this file; see the file COPYING.  If not, write to the
      19     Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
      20     MA 02110-1301, USA.  */
      21  
      22  #include "sysdep.h"
      23  #include <errno.h>
      24  #include <math.h>
      25  #include "disassemble.h"
      26  #include "opcode/tic30.h"
      27  
      28  #define NORMAL_INSN   1
      29  #define PARALLEL_INSN 2
      30  
      31  /* Gets the type of instruction based on the top 2 or 3 bits of the
      32     instruction word.  */
      33  #define GET_TYPE(insn) (insn & 0x80000000 ? insn & 0xC0000000 : insn & 0xE0000000)
      34  
      35  /* Instruction types.  */
      36  #define TWO_OPERAND_1 0x00000000
      37  #define TWO_OPERAND_2 0x40000000
      38  #define THREE_OPERAND 0x20000000
      39  #define PAR_STORE     0xC0000000
      40  #define MUL_ADDS      0x80000000
      41  #define BRANCHES      0x60000000
      42  
      43  /* Specific instruction id bits.  */
      44  #define NORMAL_IDEN    0x1F800000
      45  #define PAR_STORE_IDEN 0x3E000000
      46  #define MUL_ADD_IDEN   0x2C000000
      47  #define BR_IMM_IDEN    0x1F000000
      48  #define BR_COND_IDEN   0x1C3F0000
      49  
      50  /* Addressing modes.  */
      51  #define AM_REGISTER 0x00000000
      52  #define AM_DIRECT   0x00200000
      53  #define AM_INDIRECT 0x00400000
      54  #define AM_IMM      0x00600000
      55  
      56  #define P_FIELD 0x03000000
      57  
      58  #define REG_AR0 0x08
      59  #define LDP_INSN 0x08700000
      60  
      61  /* TMS320C30 program counter for current instruction.  */
      62  static unsigned int _pc;
      63  
      64  struct instruction
      65  {
      66    int type;
      67    insn_template *tm;
      68    partemplate *ptm;
      69  };
      70  
      71  static int
      72  get_tic30_instruction (unsigned long insn_word, struct instruction *insn)
      73  {
      74    switch (GET_TYPE (insn_word))
      75      {
      76      case TWO_OPERAND_1:
      77      case TWO_OPERAND_2:
      78      case THREE_OPERAND:
      79        insn->type = NORMAL_INSN;
      80        {
      81  	insn_template *current_optab = (insn_template *) tic30_optab;
      82  
      83  	for (; current_optab < tic30_optab_end; current_optab++)
      84  	  {
      85  	    if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
      86  	      {
      87  		if (current_optab->operands == 0)
      88  		  {
      89  		    if (current_optab->base_opcode == insn_word)
      90  		      {
      91  			insn->tm = current_optab;
      92  			break;
      93  		      }
      94  		  }
      95  		else if ((current_optab->base_opcode & NORMAL_IDEN) == (insn_word & NORMAL_IDEN))
      96  		  {
      97  		    insn->tm = current_optab;
      98  		    break;
      99  		  }
     100  	      }
     101  	  }
     102        }
     103        break;
     104  
     105      case PAR_STORE:
     106        insn->type = PARALLEL_INSN;
     107        {
     108  	partemplate *current_optab = (partemplate *) tic30_paroptab;
     109  
     110  	for (; current_optab < tic30_paroptab_end; current_optab++)
     111  	  {
     112  	    if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
     113  	      {
     114  		if ((current_optab->base_opcode & PAR_STORE_IDEN)
     115  		    == (insn_word & PAR_STORE_IDEN))
     116  		  {
     117  		    insn->ptm = current_optab;
     118  		    break;
     119  		  }
     120  	      }
     121  	  }
     122        }
     123        break;
     124  
     125      case MUL_ADDS:
     126        insn->type = PARALLEL_INSN;
     127        {
     128  	partemplate *current_optab = (partemplate *) tic30_paroptab;
     129  
     130  	for (; current_optab < tic30_paroptab_end; current_optab++)
     131  	  {
     132  	    if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
     133  	      {
     134  		if ((current_optab->base_opcode & MUL_ADD_IDEN)
     135  		    == (insn_word & MUL_ADD_IDEN))
     136  		  {
     137  		    insn->ptm = current_optab;
     138  		    break;
     139  		  }
     140  	      }
     141  	  }
     142        }
     143        break;
     144  
     145      case BRANCHES:
     146        insn->type = NORMAL_INSN;
     147        {
     148  	insn_template *current_optab = (insn_template *) tic30_optab;
     149  
     150  	for (; current_optab < tic30_optab_end; current_optab++)
     151  	  {
     152  	    if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
     153  	      {
     154  		if (current_optab->operand_types[0] & Imm24)
     155  		  {
     156  		    if ((current_optab->base_opcode & BR_IMM_IDEN)
     157  			== (insn_word & BR_IMM_IDEN))
     158  		      {
     159  			insn->tm = current_optab;
     160  			break;
     161  		      }
     162  		  }
     163  		else if (current_optab->operands > 0)
     164  		  {
     165  		    if ((current_optab->base_opcode & BR_COND_IDEN)
     166  			== (insn_word & BR_COND_IDEN))
     167  		      {
     168  			insn->tm = current_optab;
     169  			break;
     170  		      }
     171  		  }
     172  		else
     173  		  {
     174  		    if ((current_optab->base_opcode & (BR_COND_IDEN | 0x00800000))
     175  			== (insn_word & (BR_COND_IDEN | 0x00800000)))
     176  		      {
     177  			insn->tm = current_optab;
     178  			break;
     179  		      }
     180  		  }
     181  	      }
     182  	  }
     183        }
     184        break;
     185      default:
     186        return 0;
     187      }
     188    return 1;
     189  }
     190  
     191  #define OPERAND_BUFFER_LEN 15
     192  
     193  static int
     194  get_register_operand (unsigned char fragment, char *buffer)
     195  {
     196    const reg *current_reg = tic30_regtab;
     197  
     198    if (buffer == NULL)
     199      return 0;
     200    for (; current_reg < tic30_regtab_end; current_reg++)
     201      {
     202        if ((fragment & 0x1F) == current_reg->opcode)
     203  	{
     204  	  strncpy (buffer, current_reg->name, OPERAND_BUFFER_LEN - 1);
     205  	  buffer[OPERAND_BUFFER_LEN - 1] = 0;
     206  	  return 1;
     207  	}
     208      }
     209    return 0;
     210  }
     211  
     212  static int
     213  get_indirect_operand (unsigned short fragment,
     214  		      int size,
     215  		      char *buffer)
     216  {
     217    unsigned char mod;
     218    unsigned arnum;
     219    unsigned char disp;
     220  
     221    if (buffer == NULL)
     222      return 0;
     223    /* Determine which bits identify the sections of the indirect
     224       operand based on the size in bytes.  */
     225    switch (size)
     226      {
     227      case 1:
     228        mod = (fragment & 0x00F8) >> 3;
     229        arnum = (fragment & 0x0007);
     230        disp = 0;
     231        break;
     232      case 2:
     233        mod = (fragment & 0xF800) >> 11;
     234        arnum = (fragment & 0x0700) >> 8;
     235        disp = (fragment & 0x00FF);
     236        break;
     237      default:
     238        return 0;
     239      }
     240    {
     241      const ind_addr_type *current_ind = tic30_indaddr_tab;
     242  
     243      for (; current_ind < tic30_indaddrtab_end; current_ind++)
     244        {
     245  	if (current_ind->modfield == mod)
     246  	  {
     247  	    if (current_ind->displacement == IMPLIED_DISP && size == 2)
     248  	      continue;
     249  
     250  	    else
     251  	      {
     252  		size_t i, len;
     253  		int bufcnt;
     254  
     255  		len = strlen (current_ind->syntax);
     256  
     257  		for (i = 0, bufcnt = 0; i < len; i++, bufcnt++)
     258  		  {
     259  		    buffer[bufcnt] = current_ind->syntax[i];
     260  
     261  		    if (bufcnt > 0
     262  			&& bufcnt < OPERAND_BUFFER_LEN - 1
     263  			&& buffer[bufcnt - 1] == 'a'
     264  			&& buffer[bufcnt] == 'r')
     265  		      buffer[++bufcnt] = arnum + '0';
     266  		    
     267  		    if (bufcnt < OPERAND_BUFFER_LEN - 1
     268  			&& buffer[bufcnt] == '('
     269  			&& current_ind->displacement == DISP_REQUIRED)
     270  		      {
     271  			snprintf (buffer + (bufcnt + 1),
     272  				 OPERAND_BUFFER_LEN - (bufcnt + 1),
     273  				 "%u", disp);
     274  			bufcnt += strlen (buffer + (bufcnt + 1));
     275  		      }
     276  		  }
     277  		buffer[bufcnt + 1] = '\0';
     278  		break;
     279  	      }
     280  	  }
     281        }
     282    }
     283    return 1;
     284  }
     285  
     286  static int
     287  cnvt_tmsfloat_ieee (unsigned long tmsfloat, int size, float *ieeefloat)
     288  {
     289    unsigned long exponent, sign, mant;
     290    union
     291    {
     292      unsigned long l;
     293      float f;
     294    } val;
     295  
     296    if (size == 2)
     297      {
     298        if ((tmsfloat & 0x0000F000) == 0x00008000)
     299  	tmsfloat = 0x80000000;
     300        else
     301  	{
     302  	  tmsfloat <<= 16;
     303  	  tmsfloat = (long) tmsfloat >> 4;
     304  	}
     305      }
     306    exponent = tmsfloat & 0xFF000000;
     307    if (exponent == 0x80000000)
     308      {
     309        *ieeefloat = 0.0;
     310        return 1;
     311      }
     312    exponent += 0x7F000000;
     313    sign = (tmsfloat & 0x00800000) << 8;
     314    mant = tmsfloat & 0x007FFFFF;
     315    if (exponent == 0xFF000000)
     316      {
     317        if (mant == 0)
     318  	*ieeefloat = ERANGE;
     319  #ifdef HUGE_VALF
     320        if (sign == 0)
     321  	*ieeefloat = HUGE_VALF;
     322        else
     323  	*ieeefloat = -HUGE_VALF;
     324  #else
     325        if (sign == 0)
     326  	*ieeefloat = 1.0 / 0.0;
     327        else
     328  	*ieeefloat = -1.0 / 0.0;
     329  #endif
     330        return 1;
     331      }
     332    exponent >>= 1;
     333    if (sign)
     334      {
     335        mant = (~mant) & 0x007FFFFF;
     336        mant += 1;
     337        exponent += mant & 0x00800000;
     338        exponent &= 0x7F800000;
     339        mant &= 0x007FFFFF;
     340      }
     341    if (tmsfloat == 0x80000000)
     342      sign = mant = exponent = 0;
     343    tmsfloat = sign | exponent | mant;
     344    val.l = tmsfloat;
     345    *ieeefloat = val.f;
     346    return 1;
     347  }
     348  
     349  static int
     350  print_two_operand (disassemble_info *info,
     351  		   unsigned long insn_word,
     352  		   struct instruction *insn)
     353  {
     354    char name[12];
     355    char operand[2][OPERAND_BUFFER_LEN] =
     356    {
     357      {0},
     358      {0}
     359    };
     360    float f_number;
     361  
     362    if (insn->tm == NULL)
     363      return 0;
     364    strcpy (name, insn->tm->name);
     365    if (insn->tm->opcode_modifier == AddressMode)
     366      {
     367        int src_op, dest_op;
     368        /* Determine whether instruction is a store or a normal instruction.  */
     369        if ((insn->tm->operand_types[1] & (Direct | Indirect))
     370  	  == (Direct | Indirect))
     371  	{
     372  	  src_op = 1;
     373  	  dest_op = 0;
     374  	}
     375        else
     376  	{
     377  	  src_op = 0;
     378  	  dest_op = 1;
     379  	}
     380        /* Get the destination register.  */
     381        if (insn->tm->operands == 2)
     382  	get_register_operand ((insn_word & 0x001F0000) >> 16, operand[dest_op]);
     383        /* Get the source operand based on addressing mode.  */
     384        switch (insn_word & AddressMode)
     385  	{
     386  	case AM_REGISTER:
     387  	  /* Check for the NOP instruction before getting the operand.  */
     388  	  if ((insn->tm->operand_types[0] & NotReq) == 0)
     389  	    get_register_operand ((insn_word & 0x0000001F), operand[src_op]);
     390  	  break;
     391  	case AM_DIRECT:
     392  	  sprintf (operand[src_op], "@0x%lX", (insn_word & 0x0000FFFF));
     393  	  break;
     394  	case AM_INDIRECT:
     395  	  get_indirect_operand ((insn_word & 0x0000FFFF), 2, operand[src_op]);
     396  	  break;
     397  	case AM_IMM:
     398  	  /* Get the value of the immediate operand based on variable type.  */
     399  	  switch (insn->tm->imm_arg_type)
     400  	    {
     401  	    case Imm_Float:
     402  	      cnvt_tmsfloat_ieee ((insn_word & 0x0000FFFF), 2, &f_number);
     403  	      sprintf (operand[src_op], "%2.2f", f_number);
     404  	      break;
     405  	    case Imm_SInt:
     406  	      sprintf (operand[src_op], "%d", (short) (insn_word & 0x0000FFFF));
     407  	      break;
     408  	    case Imm_UInt:
     409  	      sprintf (operand[src_op], "%lu", (insn_word & 0x0000FFFF));
     410  	      break;
     411  	    default:
     412  	      return 0;
     413  	    }
     414  	  /* Handle special case for LDP instruction.  */
     415  	  if ((insn_word & 0xFFFFFF00) == LDP_INSN)
     416  	    {
     417  	      strcpy (name, "ldp");
     418  	      sprintf (operand[0], "0x%06lX", (insn_word & 0x000000FF) << 16);
     419  	      operand[1][0] = '\0';
     420  	    }
     421  	}
     422      }
     423    /* Handle case for stack and rotate instructions.  */
     424    else if (insn->tm->operands == 1)
     425      {
     426        if (insn->tm->opcode_modifier == StackOp)
     427  	get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]);
     428      }
     429    /* Output instruction to stream.  */
     430    info->fprintf_func (info->stream, "   %s %s%c%s", name,
     431  		      operand[0][0] ? operand[0] : "",
     432  		      operand[1][0] ? ',' : ' ',
     433  		      operand[1][0] ? operand[1] : "");
     434    return 1;
     435  }
     436  
     437  static int
     438  print_three_operand (disassemble_info *info,
     439  		     unsigned long insn_word,
     440  		     struct instruction *insn)
     441  {
     442    char operand[3][OPERAND_BUFFER_LEN] =
     443    {
     444      {0},
     445      {0},
     446      {0}
     447    };
     448  
     449    if (insn->tm == NULL)
     450      return 0;
     451    switch (insn_word & AddressMode)
     452      {
     453      case AM_REGISTER:
     454        get_register_operand ((insn_word & 0x000000FF), operand[0]);
     455        get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
     456        break;
     457      case AM_DIRECT:
     458        get_register_operand ((insn_word & 0x000000FF), operand[0]);
     459        get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
     460        break;
     461      case AM_INDIRECT:
     462        get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
     463        get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
     464        break;
     465      case AM_IMM:
     466        get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
     467        get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
     468        break;
     469      default:
     470        return 0;
     471      }
     472    if (insn->tm->operands == 3)
     473      get_register_operand ((insn_word & 0x001F0000) >> 16, operand[2]);
     474    info->fprintf_func (info->stream, "   %s %s,%s%c%s", insn->tm->name,
     475  		      operand[0], operand[1],
     476  		      operand[2][0] ? ',' : ' ',
     477  		      operand[2][0] ? operand[2] : "");
     478    return 1;
     479  }
     480  
     481  static int
     482  print_par_insn (disassemble_info *info,
     483  		unsigned long insn_word,
     484  		struct instruction *insn)
     485  {
     486    size_t i, len;
     487    char *name1, *name2;
     488    char operand[2][3][OPERAND_BUFFER_LEN] =
     489    {
     490      {
     491        {0},
     492        {0},
     493        {0}
     494      },
     495      {
     496        {0},
     497        {0},
     498        {0}
     499      }
     500    };
     501  
     502    if (insn->ptm == NULL)
     503      return 0;
     504    /* Parse out the names of each of the parallel instructions from the
     505       q_insn1_insn2 format.  */
     506    name1 = (char *) strdup (insn->ptm->name + 2);
     507    name2 = "";
     508    len = strlen (name1);
     509    for (i = 0; i < len; i++)
     510      {
     511        if (name1[i] == '_')
     512  	{
     513  	  name2 = &name1[i + 1];
     514  	  name1[i] = '\0';
     515  	  break;
     516  	}
     517      }
     518    /* Get the operands of the instruction based on the operand order.  */
     519    switch (insn->ptm->oporder)
     520      {
     521      case OO_4op1:
     522        get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
     523        get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
     524        get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
     525        get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
     526        break;
     527      case OO_4op2:
     528        get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
     529        get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
     530        get_register_operand ((insn_word >> 19) & 0x07, operand[1][1]);
     531        get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
     532        break;
     533      case OO_4op3:
     534        get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
     535        get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
     536        get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
     537        get_register_operand ((insn_word >> 22) & 0x07, operand[0][0]);
     538        break;
     539      case OO_5op1:
     540        get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
     541        get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
     542        get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
     543        get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
     544        get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
     545        break;
     546      case OO_5op2:
     547        get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
     548        get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
     549        get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
     550        get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
     551        get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
     552        break;
     553      case OO_PField:
     554        if (insn_word & 0x00800000)
     555  	get_register_operand (0x01, operand[0][2]);
     556        else
     557  	get_register_operand (0x00, operand[0][2]);
     558        if (insn_word & 0x00400000)
     559  	get_register_operand (0x03, operand[1][2]);
     560        else
     561  	get_register_operand (0x02, operand[1][2]);
     562        switch (insn_word & P_FIELD)
     563  	{
     564  	case 0x00000000:
     565  	  get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
     566  	  get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
     567  	  get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
     568  	  get_register_operand ((insn_word >> 19) & 0x07, operand[1][0]);
     569  	  break;
     570  	case 0x01000000:
     571  	  get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][0]);
     572  	  get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
     573  	  get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
     574  	  get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
     575  	  break;
     576  	case 0x02000000:
     577  	  get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
     578  	  get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
     579  	  get_register_operand ((insn_word >> 16) & 0x07, operand[0][1]);
     580  	  get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
     581  	  break;
     582  	case 0x03000000:
     583  	  get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
     584  	  get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
     585  	  get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
     586  	  get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
     587  	  break;
     588  	}
     589        break;
     590      default:
     591        return 0;
     592      }
     593    info->fprintf_func (info->stream, "   %s %s,%s%c%s", name1,
     594  		      operand[0][0], operand[0][1],
     595  		      operand[0][2][0] ? ',' : ' ',
     596  		      operand[0][2][0] ? operand[0][2] : "");
     597    info->fprintf_func (info->stream, "\n\t\t\t|| %s %s,%s%c%s", name2,
     598  		      operand[1][0], operand[1][1],
     599  		      operand[1][2][0] ? ',' : ' ',
     600  		      operand[1][2][0] ? operand[1][2] : "");
     601    free (name1);
     602    return 1;
     603  }
     604  
     605  static int
     606  print_branch (disassemble_info *info,
     607  	      unsigned long insn_word,
     608  	      struct instruction *insn)
     609  {
     610    char operand[2][OPERAND_BUFFER_LEN] =
     611    {
     612      {0},
     613      {0}
     614    };
     615    unsigned long address;
     616    int print_label = 0;
     617  
     618    if (insn->tm == NULL)
     619      return 0;
     620    /* Get the operands for 24-bit immediate jumps.  */
     621    if (insn->tm->operand_types[0] & Imm24)
     622      {
     623        address = insn_word & 0x00FFFFFF;
     624        sprintf (operand[0], "0x%lX", address);
     625        print_label = 1;
     626      }
     627    /* Get the operand for the trap instruction.  */
     628    else if (insn->tm->operand_types[0] & IVector)
     629      {
     630        address = insn_word & 0x0000001F;
     631        sprintf (operand[0], "0x%lX", address);
     632      }
     633    else
     634      {
     635        address = insn_word & 0x0000FFFF;
     636        /* Get the operands for the DB instructions.  */
     637        if (insn->tm->operands == 2)
     638  	{
     639  	  get_register_operand (((insn_word & 0x01C00000) >> 22) + REG_AR0, operand[0]);
     640  	  if (insn_word & PCRel)
     641  	    {
     642  	      sprintf (operand[1], "%d", (short) address);
     643  	      print_label = 1;
     644  	    }
     645  	  else
     646  	    get_register_operand (insn_word & 0x0000001F, operand[1]);
     647  	}
     648        /* Get the operands for the standard branches.  */
     649        else if (insn->tm->operands == 1)
     650  	{
     651  	  if (insn_word & PCRel)
     652  	    {
     653  	      address = (short) address;
     654  	      sprintf (operand[0], "%ld", address);
     655  	      print_label = 1;
     656  	    }
     657  	  else
     658  	    get_register_operand (insn_word & 0x0000001F, operand[0]);
     659  	}
     660      }
     661    info->fprintf_func (info->stream, "   %s %s%c%s", insn->tm->name,
     662  		      operand[0][0] ? operand[0] : "",
     663  		      operand[1][0] ? ',' : ' ',
     664  		      operand[1][0] ? operand[1] : "");
     665    /* Print destination of branch in relation to current symbol.  */
     666    if (print_label && info->symbols)
     667      {
     668        asymbol *sym = *info->symbols;
     669  
     670        if ((insn->tm->opcode_modifier == PCRel) && (insn_word & PCRel))
     671  	{
     672  	  address = (_pc + 1 + (short) address) - ((sym->section->vma + sym->value) / 4);
     673  	  /* Check for delayed instruction, if so adjust destination.  */
     674  	  if (insn_word & 0x00200000)
     675  	    address += 2;
     676  	}
     677        else
     678  	{
     679  	  address -= ((sym->section->vma + sym->value) / 4);
     680  	}
     681        if (address == 0)
     682  	info->fprintf_func (info->stream, " <%s>", sym->name);
     683        else
     684  	info->fprintf_func (info->stream, " <%s %c %lu>", sym->name,
     685  			    ((short) address < 0) ? '-' : '+',
     686  			    address);
     687      }
     688    return 1;
     689  }
     690  
     691  int
     692  print_insn_tic30 (bfd_vma pc, disassemble_info *info)
     693  {
     694    unsigned long insn_word;
     695    struct instruction insn = { 0, NULL, NULL };
     696    bfd_vma bufaddr = pc - info->buffer_vma;
     697  
     698    if (bufaddr + 3 >= info->buffer_length)
     699      return -1;
     700  
     701    /* Obtain the current instruction word from the buffer.  */
     702    insn_word = (((unsigned) *(info->buffer + bufaddr) << 24)
     703  	       | (*(info->buffer + bufaddr + 1) << 16)
     704  	       | (*(info->buffer + bufaddr + 2) << 8)
     705  	       | *(info->buffer + bufaddr + 3));
     706    _pc = pc / 4;
     707    /* Get the instruction referred to by the current instruction word
     708       and print it out based on its type.  */
     709    if (!get_tic30_instruction (insn_word, &insn))
     710      return -1;
     711    switch (GET_TYPE (insn_word))
     712      {
     713      case TWO_OPERAND_1:
     714      case TWO_OPERAND_2:
     715        if (!print_two_operand (info, insn_word, &insn))
     716  	return -1;
     717        break;
     718      case THREE_OPERAND:
     719        if (!print_three_operand (info, insn_word, &insn))
     720  	return -1;
     721        break;
     722      case PAR_STORE:
     723      case MUL_ADDS:
     724        if (!print_par_insn (info, insn_word, &insn))
     725  	return -1;
     726        break;
     727      case BRANCHES:
     728        if (!print_branch (info, insn_word, &insn))
     729  	return -1;
     730        break;
     731      }
     732    return 4;
     733  }