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