Home | History | Annotate | Download | only in opcodes
      1 /* TI C6X disassembler.
      2    Copyright (C) 2010-2016 Free Software Foundation, Inc.
      3    Contributed by Joseph Myers <joseph (at) codesourcery.com>
      4    		  Bernd Schmidt  <bernds (at) codesourcery.com>
      5 
      6    This file is part of libopcodes.
      7 
      8    This library is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    It is distributed in the hope that it will be useful, but WITHOUT
     14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     16    License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21    MA 02110-1301, USA.  */
     22 
     23 #include "sysdep.h"
     24 #include "dis-asm.h"
     25 #include "opcode/tic6x.h"
     26 #include "libiberty.h"
     27 
     28 /* Define the instruction format table.  */
     29 const tic6x_insn_format tic6x_insn_format_table[tic6x_insn_format_max] =
     30   {
     31 #define FMT(name, num_bits, cst_bits, mask, fields) \
     32     { num_bits, cst_bits, mask, fields },
     33 #include "opcode/tic6x-insn-formats.h"
     34 #undef FMT
     35   };
     36 
     37 /* Define the control register table.  */
     38 const tic6x_ctrl tic6x_ctrl_table[tic6x_ctrl_max] =
     39   {
     40 #define CTRL(name, isa, rw, crlo, crhi_mask)	\
     41     {						\
     42       STRINGX(name),				\
     43       CONCAT2(TIC6X_INSN_,isa),			\
     44       CONCAT2(tic6x_rw_,rw),			\
     45       crlo,					\
     46       crhi_mask					\
     47     },
     48 #include "opcode/tic6x-control-registers.h"
     49 #undef CTRL
     50   };
     51 
     52 /* Define the opcode table.  */
     53 const tic6x_opcode tic6x_opcode_table[tic6x_opcode_max] =
     54   {
     55 #define INSNU(name, func_unit, format, type, isa, flags, fixed, ops, var) \
     56     {									\
     57       STRINGX(name),							\
     58       CONCAT2(tic6x_func_unit_,func_unit),				\
     59       CONCAT3(tic6x_insn_format,_,format),	      			\
     60       CONCAT2(tic6x_pipeline_,type),					\
     61       CONCAT2(TIC6X_INSN_,isa),						\
     62       flags,								\
     63       fixed,								\
     64       ops,								\
     65       var								\
     66     },
     67 #define INSNUE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
     68     {									\
     69       STRINGX(name),							\
     70       CONCAT2(tic6x_func_unit_,func_unit),				\
     71       CONCAT3(tic6x_insn_format,_,format),	      			\
     72       CONCAT2(tic6x_pipeline_,type),					\
     73       CONCAT2(TIC6X_INSN_,isa),						\
     74       flags,								\
     75       fixed,								\
     76       ops,								\
     77       var								\
     78     },
     79 #define INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \
     80     {									\
     81       STRINGX(name),							\
     82       CONCAT2(tic6x_func_unit_,func_unit),				\
     83       CONCAT4(tic6x_insn_format_,func_unit,_,format),			\
     84       CONCAT2(tic6x_pipeline_,type),					\
     85       CONCAT2(TIC6X_INSN_,isa),						\
     86       flags,								\
     87       fixed,								\
     88       ops,								\
     89       var								\
     90     },
     91 #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
     92     {									\
     93       STRINGX(name),							\
     94       CONCAT2(tic6x_func_unit_,func_unit),				\
     95       CONCAT4(tic6x_insn_format_,func_unit,_,format),			\
     96       CONCAT2(tic6x_pipeline_,type),					\
     97       CONCAT2(TIC6X_INSN_,isa),						\
     98       flags,								\
     99       fixed,								\
    100       ops,								\
    101       var								\
    102     },
    103 #include "opcode/tic6x-opcode-table.h"
    104 #undef INSN
    105 #undef INSNE
    106 #undef INSNU
    107 #undef INSNUE
    108   };
    109 
    110 /* If instruction format FMT has a field FIELD, return a pointer to
    111    the description of that field; otherwise return NULL.  */
    112 
    113 const tic6x_insn_field *
    114 tic6x_field_from_fmt (const tic6x_insn_format *fmt, tic6x_insn_field_id field)
    115 {
    116   unsigned int f;
    117 
    118   for (f = 0; f < fmt->num_fields; f++)
    119     if (fmt->fields[f].field_id == field)
    120       return &fmt->fields[f];
    121 
    122   return NULL;
    123 }
    124 
    125 /* Extract the field width.  */
    126 
    127 static unsigned int
    128 tic6x_field_width (const tic6x_insn_field *field)
    129 {
    130   unsigned int i;
    131   unsigned int width = 0;
    132 
    133   if (!field->num_bitfields)
    134     return field->bitfields[0].width;
    135 
    136   for (i = 0 ; i < field->num_bitfields ; i++)
    137     width += field->bitfields[i].width;
    138 
    139   return width;
    140 }
    141 
    142 /* Extract the bits corresponding to FIELD from OPCODE.  */
    143 
    144 static unsigned int
    145 tic6x_field_bits (unsigned int opcode, const tic6x_insn_field *field)
    146 {
    147   unsigned int i;
    148   unsigned int val = 0;
    149 
    150   if (!field->num_bitfields)
    151     return (opcode >> field->bitfields[0].low_pos) & ((1u << field->bitfields[0].width) - 1);
    152 
    153   for (i = 0 ; i < field->num_bitfields ; i++)
    154     val |= ((opcode >> field->bitfields[i].low_pos) & ((1u << field->bitfields[i].width) - 1))
    155       << field->bitfields[i].pos;
    156 
    157   return val;
    158 }
    159 
    160 /* Extract a 32-bit value read from the instruction stream.  */
    161 
    162 static unsigned int
    163 tic6x_extract_32 (unsigned char *p, struct disassemble_info *info)
    164 {
    165   if (info->endian == BFD_ENDIAN_LITTLE)
    166     return (p[0]) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
    167   else
    168     return (p[3]) | (p[2] << 8) | (p[1] << 16) | (p[0] << 24);
    169 }
    170 
    171 /* Extract a 16-bit value read from the instruction stream.  */
    172 
    173 static unsigned int
    174 tic6x_extract_16 (unsigned char *p, tic6x_fetch_packet_header *header,
    175                   struct disassemble_info *info)
    176 {
    177   unsigned int op16;
    178 
    179   if (info->endian == BFD_ENDIAN_LITTLE)
    180     op16 = (p[0]) | (p[1] << 8);
    181   else
    182     op16 = (p[1]) | (p[0] << 8);
    183   op16 |= (header->sat << TIC6X_COMPACT_SAT_POS);
    184   op16 |= (header->br << TIC6X_COMPACT_BR_POS);
    185   op16 |= (header->dsz << TIC6X_COMPACT_DSZ_POS);
    186   return op16;
    187 }
    188 
    189 /* FP points to a fetch packet.  Return whether it is header-based; if
    190    it is, fill in HEADER.  */
    191 
    192 static bfd_boolean
    193 tic6x_check_fetch_packet_header (unsigned char *fp,
    194 				 tic6x_fetch_packet_header *header,
    195 				 struct disassemble_info *info)
    196 {
    197   int i;
    198 
    199   header->header = tic6x_extract_32 (fp + 28, info);
    200 
    201   if ((header->header & 0xf0000000) != 0xe0000000)
    202     {
    203       header->prot = 0;
    204       header->rs = 0;
    205       header->dsz = 0;
    206       header->br = 0;
    207       header->sat = 0;
    208       for (i = 0; i < 7; i++)
    209 	header->word_compact[i] = FALSE;
    210       for (i = 0; i < 14; i++)
    211 	header->p_bits[i] = FALSE;
    212       return FALSE;
    213     }
    214 
    215   for (i = 0; i < 7; i++)
    216     header->word_compact[i]
    217       = (header->header & (1u << (21 + i))) ? TRUE : FALSE;
    218 
    219   header->prot = (header->header & (1u << 20)) ? TRUE : FALSE;
    220   header->rs = (header->header & (1u << 19)) ? TRUE : FALSE;
    221   header->dsz = (header->header >> 16) & 0x7;
    222   header->br = (header->header & (1u << 15)) ? TRUE : FALSE;
    223   header->sat = (header->header & (1u << 14)) ? TRUE : FALSE;
    224 
    225   for (i = 0; i < 14; i++)
    226     header->p_bits[i]
    227       = (header->header & (1u << i)) ? TRUE : FALSE;
    228 
    229   return TRUE;
    230 }
    231 
    232 /* Disassemble the instruction at ADDR and print it using
    233    INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes
    234    consumed.  */
    235 
    236 int
    237 print_insn_tic6x (bfd_vma addr, struct disassemble_info *info)
    238 {
    239   int status;
    240   bfd_vma fp_addr;
    241   bfd_vma fp_offset;
    242   unsigned char fp[32];
    243   unsigned int opcode;
    244   tic6x_opcode_id opcode_id;
    245   bfd_boolean fetch_packet_header_based;
    246   tic6x_fetch_packet_header header;
    247   unsigned int num_bits;
    248   bfd_boolean bad_offset = FALSE;
    249 
    250   fp_offset = addr & 0x1f;
    251   fp_addr = addr - fp_offset;
    252   /* Read in a block of instructions.  Since there might be a
    253      symbol in the middle of this block, disable stop_vma.  */
    254   info->stop_vma = 0;
    255   status = info->read_memory_func (fp_addr, fp, 32, info);
    256   if (status)
    257     {
    258       info->memory_error_func (status, addr, info);
    259       return -1;
    260     }
    261 
    262   fetch_packet_header_based
    263     = tic6x_check_fetch_packet_header (fp, &header, info);
    264   if (fetch_packet_header_based)
    265     {
    266       if (fp_offset & 0x1)
    267 	bad_offset = TRUE;
    268       if ((fp_offset & 0x3) && (fp_offset >= 28
    269 				|| !header.word_compact[fp_offset >> 2]))
    270 	bad_offset = TRUE;
    271       if (fp_offset == 28)
    272 	{
    273 	  info->bytes_per_chunk = 4;
    274 	  info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>",
    275 			      header.header);
    276 	  return 4;
    277 	}
    278       num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32);
    279     }
    280   else
    281     {
    282       num_bits = 32;
    283       if (fp_offset & 0x3)
    284 	bad_offset = TRUE;
    285     }
    286 
    287   if (bad_offset)
    288     {
    289       info->bytes_per_chunk = 1;
    290       info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]);
    291       return 1;
    292     }
    293 
    294   if (num_bits == 16)
    295     {
    296       /* The least-significant part of a 32-bit word comes logically
    297 	 before the most-significant part.  For big-endian, follow the
    298 	 TI assembler in showing instructions in logical order by
    299 	 pretending that the two halves of the word are in opposite
    300 	 locations to where they actually are.  */
    301       if (info->endian == BFD_ENDIAN_LITTLE)
    302 	opcode = tic6x_extract_16 (fp + fp_offset, &header, info);
    303       else
    304 	opcode = tic6x_extract_16 (fp + (fp_offset ^ 2), &header, info);
    305     }
    306   else
    307     opcode = tic6x_extract_32 (fp + fp_offset, info);
    308 
    309   for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++)
    310     {
    311       const tic6x_opcode *const opc = &tic6x_opcode_table[opcode_id];
    312       const tic6x_insn_format *const fmt
    313 	= &tic6x_insn_format_table[opc->format];
    314       const tic6x_insn_field *creg_field;
    315       bfd_boolean p_bit;
    316       const char *parallel;
    317       const char *cond = "";
    318       const char *func_unit;
    319       char func_unit_buf[7];
    320       unsigned int func_unit_side = 0;
    321       unsigned int func_unit_data_side = 0;
    322       unsigned int func_unit_cross = 0;
    323       unsigned int t_val = 0;
    324       /* The maximum length of the text of a non-PC-relative operand
    325 	 is 24 bytes (SPMASK masking all eight functional units, with
    326 	 separating commas and trailing NUL).  */
    327       char operands[TIC6X_MAX_OPERANDS][24] = { { 0 } };
    328       bfd_vma operands_addresses[TIC6X_MAX_OPERANDS] = { 0 };
    329       bfd_boolean operands_text[TIC6X_MAX_OPERANDS] = { FALSE };
    330       bfd_boolean operands_pcrel[TIC6X_MAX_OPERANDS] = { FALSE };
    331       unsigned int fix;
    332       unsigned int num_operands;
    333       unsigned int op_num;
    334       bfd_boolean fixed_ok;
    335       bfd_boolean operands_ok;
    336       bfd_boolean have_t = FALSE;
    337 
    338       if (opc->flags & TIC6X_FLAG_MACRO)
    339 	continue;
    340       if (fmt->num_bits != num_bits)
    341 	continue;
    342       if ((opcode & fmt->mask) != fmt->cst_bits)
    343 	continue;
    344 
    345       /* If the format has a creg field, it is only a candidate for a
    346 	 match if the creg and z fields have values indicating a valid
    347 	 condition; reserved values indicate either an instruction
    348 	 format without a creg field, or an invalid instruction.  */
    349       creg_field = tic6x_field_from_fmt (fmt, tic6x_field_creg);
    350       if (creg_field)
    351 	{
    352 	  const tic6x_insn_field *z_field;
    353 	  unsigned int creg_value, z_value;
    354 	  static const char *const conds[8][2] =
    355 	    {
    356 	      { "", NULL },
    357 	      { "[b0] ", "[!b0] " },
    358 	      { "[b1] ", "[!b1] " },
    359 	      { "[b2] ", "[!b2] " },
    360 	      { "[a1] ", "[!a1] " },
    361 	      { "[a2] ", "[!a2] " },
    362 	      { "[a0] ", "[!a0] " },
    363 	      { NULL, NULL }
    364 	    };
    365 
    366 	  /* A creg field is not meaningful without a z field, so if
    367 	     the z field is not present this is an error in the format
    368 	     table.  */
    369 	  z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
    370 	  if (!z_field)
    371 	    {
    372 	      printf ("*** opcode %x: missing z field", opcode);
    373 	      abort ();
    374 	    }
    375 
    376 	  creg_value = tic6x_field_bits (opcode, creg_field);
    377 	  z_value = tic6x_field_bits (opcode, z_field);
    378 	  cond = conds[creg_value][z_value];
    379 	  if (cond == NULL)
    380 	    continue;
    381 	}
    382 
    383       if (opc->flags & TIC6X_FLAG_INSN16_SPRED)
    384 	{
    385 	  const tic6x_insn_field *cc_field;
    386           unsigned int s_value = 0;
    387           unsigned int z_value = 0;
    388           bfd_boolean cond_known = FALSE;
    389           static const char *const conds[2][2] =
    390             {
    391               { "[a0] ", "[!a0] " },
    392               { "[b0] ", "[!b0] " }
    393             };
    394 
    395           cc_field = tic6x_field_from_fmt (fmt, tic6x_field_cc);
    396 
    397           if (cc_field)
    398 	    {
    399 	      unsigned int cc_value;
    400 
    401 	      cc_value = tic6x_field_bits (opcode, cc_field);
    402 	      s_value = (cc_value & 0x2) >> 1;
    403 	      z_value = (cc_value & 0x1);
    404 	      cond_known = TRUE;
    405 	    }
    406 	  else
    407 	    {
    408 	      const tic6x_insn_field *z_field;
    409 	      const tic6x_insn_field *s_field;
    410 
    411 	      s_field = tic6x_field_from_fmt (fmt, tic6x_field_s);
    412 
    413 	      if (!s_field)
    414 		{
    415 		  printf ("opcode %x: missing compact insn predicate register field (s field)\n",
    416 			  opcode);
    417 		  abort ();
    418 		}
    419 	      s_value = tic6x_field_bits (opcode, s_field);
    420 	      z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
    421 	      if (!z_field)
    422 		{
    423 		  printf ("opcode %x: missing compact insn predicate z_value (z field)\n", opcode);
    424 		  abort ();
    425 		}
    426 
    427 	      z_value = tic6x_field_bits (opcode, z_field);
    428 	      cond_known = TRUE;
    429 	    }
    430 
    431           if (!cond_known)
    432 	    {
    433 	      printf ("opcode %x: unspecified ompact insn predicate\n", opcode);
    434 	      abort ();
    435 	    }
    436           cond = conds[s_value][z_value];
    437 	}
    438 
    439       /* All fixed fields must have matching values; all fields with
    440 	 restricted ranges must have values within those ranges.  */
    441       fixed_ok = TRUE;
    442       for (fix = 0; fix < opc->num_fixed_fields; fix++)
    443 	{
    444 	  unsigned int field_bits;
    445 	  const tic6x_insn_field *const field
    446 	    = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id);
    447 
    448 	  if (!field)
    449 	    {
    450 	      printf ("opcode %x: missing field #%d for FIX #%d\n",
    451 		      opcode, opc->fixed_fields[fix].field_id, fix);
    452 	      abort ();
    453 	    }
    454 
    455 	  field_bits = tic6x_field_bits (opcode, field);
    456 	  if (field_bits < opc->fixed_fields[fix].min_val
    457 	      || field_bits > opc->fixed_fields[fix].max_val)
    458 	    {
    459 	      fixed_ok = FALSE;
    460 	      break;
    461 	    }
    462 	}
    463       if (!fixed_ok)
    464 	continue;
    465 
    466       /* The instruction matches.  */
    467 
    468       /* The p-bit indicates whether this instruction is in parallel
    469 	 with the *next* instruction, whereas the parallel bars
    470 	 indicate the instruction is in parallel with the *previous*
    471 	 instruction.  Thus, we must find the p-bit for the previous
    472 	 instruction.  */
    473       if (num_bits == 16 && (fp_offset & 0x2) == 2)
    474 	{
    475 	  /* This is the logically second (most significant; second in
    476 	     fp_offset terms because fp_offset relates to logical not
    477 	     physical addresses) instruction of a compact pair; find
    478 	     the p-bit for the first (least significant).  */
    479 	  p_bit = header.p_bits[(fp_offset >> 2) << 1];
    480 	}
    481       else if (fp_offset >= 4)
    482 	{
    483 	  /* Find the last instruction of the previous word in this
    484 	     fetch packet.  For compact instructions, this is the most
    485 	     significant 16 bits.  */
    486 	  if (fetch_packet_header_based
    487 	      && header.word_compact[(fp_offset >> 2) - 1])
    488 	    p_bit = header.p_bits[(fp_offset >> 1) - 1];
    489 	  else
    490 	    {
    491 	      unsigned int prev_opcode
    492 		= tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info);
    493 	      p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
    494 	    }
    495 	}
    496       else
    497 	{
    498 	  /* Find the last instruction of the previous fetch
    499 	     packet.  */
    500 	  unsigned char fp_prev[32];
    501 
    502 	  status = info->read_memory_func (fp_addr - 32, fp_prev, 32, info);
    503 	  if (status)
    504 	    /* No previous instruction to be parallel with.  */
    505 	    p_bit = FALSE;
    506 	  else
    507 	    {
    508 	      bfd_boolean prev_header_based;
    509 	      tic6x_fetch_packet_header prev_header;
    510 
    511 	      prev_header_based
    512 		= tic6x_check_fetch_packet_header (fp_prev, &prev_header, info);
    513 	      if (prev_header_based && prev_header.word_compact[6])
    514 		p_bit = prev_header.p_bits[13];
    515 	      else
    516 		{
    517 		  unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28,
    518 							       info);
    519 		  p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
    520 		}
    521 	    }
    522 	}
    523       parallel = p_bit ? "|| " : "";
    524 
    525       if (opc->func_unit == tic6x_func_unit_nfu)
    526 	func_unit = "";
    527       else
    528 	{
    529 	  unsigned int fld_num;
    530 	  char func_unit_char;
    531 	  const char *data_str;
    532 	  bfd_boolean have_areg = FALSE;
    533 	  bfd_boolean have_cross = FALSE;
    534 
    535 	  func_unit_side = (opc->flags & TIC6X_FLAG_SIDE_B_ONLY) ? 2 : 0;
    536 	  func_unit_cross = 0;
    537 	  func_unit_data_side = (opc->flags & TIC6X_FLAG_SIDE_T2_ONLY) ? 2 : 0;
    538 
    539 	  for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
    540 	    {
    541 	      const tic6x_coding_field *const enc = &opc->variable_fields[fld_num];
    542 	      const tic6x_insn_field *field;
    543 	      unsigned int fld_val;
    544 
    545 	      field = tic6x_field_from_fmt (fmt, enc->field_id);
    546 
    547 	      if (!field)
    548 		{
    549 		  printf ("opcode %x: could not retrieve field (field_id:%d)\n",
    550 			  opcode, fld_num);
    551 		  abort ();
    552 		}
    553 
    554 	      fld_val = tic6x_field_bits (opcode, field);
    555 
    556 	      switch (enc->coding_method)
    557 		{
    558 		case tic6x_coding_fu:
    559 		  /* The side must be specified exactly once.  */
    560 		  if (func_unit_side)
    561 		    {
    562 		      printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
    563 			      opcode, fld_num);
    564 		      abort ();
    565 		    }
    566 		  func_unit_side = (fld_val ? 2 : 1);
    567 		  break;
    568 
    569 		case tic6x_coding_data_fu:
    570 		  /* The data side must be specified exactly once.  */
    571 		  if (func_unit_data_side)
    572 		    {
    573 		      printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
    574 			      opcode, fld_num);
    575 		      abort ();
    576 		    }
    577 		  func_unit_data_side = (fld_val ? 2 : 1);
    578 		  break;
    579 
    580 		case tic6x_coding_xpath:
    581 		  /* Cross path use must be specified exactly
    582 		     once.  */
    583 		  if (have_cross)
    584 		    {
    585 		      printf ("opcode %x: field #%d use tic6x_coding_xpath, have_cross is already set!\n",
    586 			      opcode, fld_num);
    587 		      abort ();
    588 		    }
    589 		  have_cross = TRUE;
    590 		  func_unit_cross = fld_val;
    591 		  break;
    592 
    593                 case tic6x_coding_rside:
    594                   /* If the format has a t field, use it for src/dst register side.  */
    595                   have_t = TRUE;
    596                   t_val = fld_val;
    597                   func_unit_data_side = (t_val ? 2 : 1);
    598                   break;
    599 
    600 		case tic6x_coding_areg:
    601 		  have_areg = TRUE;
    602 		  break;
    603 
    604 		default:
    605 		  /* Don't relate to functional units.  */
    606 		  break;
    607 		}
    608 	    }
    609 
    610 	  /* The side of the functional unit used must now have been
    611 	     determined either from the flags or from an instruction
    612 	     field.  */
    613 	  if (func_unit_side != 1 && func_unit_side != 2)
    614 	    {
    615 	      printf ("opcode %x: func_unit_side is not encoded!\n", opcode);
    616 	      abort ();
    617 	    }
    618 
    619 	  /* Cross paths are not applicable when sides are specified
    620 	     for both address and data paths.  */
    621 	  if (func_unit_data_side && have_cross)
    622 	    {
    623 	      printf ("opcode %x: xpath not applicable when side are specified both for address and data!\n",
    624 		      opcode);
    625 	      abort ();
    626 	    }
    627 
    628 	  /* Separate address and data paths are only applicable for
    629 	     the D unit.  */
    630 	  if (func_unit_data_side && opc->func_unit != tic6x_func_unit_d)
    631 	    {
    632 	      printf ("opcode %x: separate address and data paths only applicable for D unit!\n",
    633 		      opcode);
    634 	      abort ();
    635           }
    636 
    637 	  /* If an address register is being used but in ADDA rather
    638 	     than a load or store, it uses a cross path for side-A
    639 	     instructions, and the cross path use is not specified by
    640 	     an instruction field.  */
    641 	  if (have_areg && !func_unit_data_side)
    642 	    {
    643 	      if (have_cross)
    644 		{
    645 		  printf ("opcode %x: illegal cross path specifier in adda opcode!\n", opcode);
    646 		  abort ();
    647 		}
    648 	      func_unit_cross = (func_unit_side == 1 ? TRUE : FALSE);
    649 	    }
    650 
    651 	  switch (opc->func_unit)
    652 	    {
    653 	    case tic6x_func_unit_d:
    654 	      func_unit_char = 'D';
    655 	      break;
    656 
    657 	    case tic6x_func_unit_l:
    658 	      func_unit_char = 'L';
    659 	      break;
    660 
    661 	    case tic6x_func_unit_m:
    662 	      func_unit_char = 'M';
    663 	      break;
    664 
    665 	    case tic6x_func_unit_s:
    666 	      func_unit_char = 'S';
    667 	      break;
    668 
    669 	    default:
    670               printf ("opcode %x: illegal func_unit specifier %d\n", opcode, opc->func_unit);
    671 	      abort ();
    672 	    }
    673 
    674 	  switch (func_unit_data_side)
    675 	    {
    676 	    case 0:
    677 	      data_str = "";
    678 	      break;
    679 
    680 	    case 1:
    681 	      data_str = "T1";
    682 	      break;
    683 
    684 	    case 2:
    685 	      data_str = "T2";
    686 	      break;
    687 
    688 	    default:
    689               printf ("opcode %x: illegal data func_unit specifier %d\n",
    690 		      opcode, func_unit_data_side);
    691 	      abort ();
    692 	    }
    693 
    694 	  if (opc->flags & TIC6X_FLAG_INSN16_BSIDE && func_unit_side == 1)
    695 	      func_unit_cross = 1;
    696 
    697 	  snprintf (func_unit_buf, 7, " .%c%u%s%s", func_unit_char,
    698 		    func_unit_side, (func_unit_cross ? "X" : ""), data_str);
    699 	  func_unit = func_unit_buf;
    700 	}
    701 
    702       /* For each operand there must be one or more fields set based
    703 	 on that operand, that can together be used to derive the
    704 	 operand value.  */
    705       operands_ok = TRUE;
    706       num_operands = opc->num_operands;
    707       for (op_num = 0; op_num < num_operands; op_num++)
    708 	{
    709 	  unsigned int fld_num;
    710 	  unsigned int mem_base_reg = 0;
    711 	  bfd_boolean mem_base_reg_known = FALSE;
    712 	  bfd_boolean mem_base_reg_known_long = FALSE;
    713 	  unsigned int mem_offset = 0;
    714 	  bfd_boolean mem_offset_known = FALSE;
    715 	  bfd_boolean mem_offset_known_long = FALSE;
    716 	  unsigned int mem_mode = 0;
    717 	  bfd_boolean mem_mode_known = FALSE;
    718 	  unsigned int mem_scaled = 0;
    719 	  bfd_boolean mem_scaled_known = FALSE;
    720 	  unsigned int crlo = 0;
    721 	  bfd_boolean crlo_known = FALSE;
    722 	  unsigned int crhi = 0;
    723 	  bfd_boolean crhi_known = FALSE;
    724 	  bfd_boolean spmask_skip_operand = FALSE;
    725 	  unsigned int fcyc_bits = 0;
    726 	  bfd_boolean prev_sploop_found = FALSE;
    727 
    728 	  switch (opc->operand_info[op_num].form)
    729 	    {
    730 	    case tic6x_operand_b15reg:
    731 	      /* Fully determined by the functional unit.  */
    732 	      operands_text[op_num] = TRUE;
    733 	      snprintf (operands[op_num], 24, "b15");
    734 	      continue;
    735 
    736 	    case tic6x_operand_zreg:
    737 	      /* Fully determined by the functional unit.  */
    738 	      operands_text[op_num] = TRUE;
    739 	      snprintf (operands[op_num], 24, "%c0",
    740 			(func_unit_side == 2 ? 'b' : 'a'));
    741 	      continue;
    742 
    743 	    case tic6x_operand_retreg:
    744 	      /* Fully determined by the functional unit.  */
    745 	      operands_text[op_num] = TRUE;
    746 	      snprintf (operands[op_num], 24, "%c3",
    747 			(func_unit_side == 2 ? 'b' : 'a'));
    748 	      continue;
    749 
    750 	    case tic6x_operand_irp:
    751 	      operands_text[op_num] = TRUE;
    752 	      snprintf (operands[op_num], 24, "irp");
    753 	      continue;
    754 
    755 	    case tic6x_operand_nrp:
    756 	      operands_text[op_num] = TRUE;
    757 	      snprintf (operands[op_num], 24, "nrp");
    758 	      continue;
    759 
    760 	    case tic6x_operand_ilc:
    761 	      operands_text[op_num] = TRUE;
    762 	      snprintf (operands[op_num], 24, "ilc");
    763 	      continue;
    764 
    765 	    case tic6x_operand_hw_const_minus_1:
    766 	      operands_text[op_num] = TRUE;
    767 	      snprintf (operands[op_num], 24, "-1");
    768 	      continue;
    769 
    770 	    case tic6x_operand_hw_const_0:
    771 	      operands_text[op_num] = TRUE;
    772 	      snprintf (operands[op_num], 24, "0");
    773 	      continue;
    774 
    775 	    case tic6x_operand_hw_const_1:
    776 	      operands_text[op_num] = TRUE;
    777 	      snprintf (operands[op_num], 24, "1");
    778 	      continue;
    779 
    780 	    case tic6x_operand_hw_const_5:
    781 	      operands_text[op_num] = TRUE;
    782 	      snprintf (operands[op_num], 24, "5");
    783 	      continue;
    784 
    785 	    case tic6x_operand_hw_const_16:
    786 	      operands_text[op_num] = TRUE;
    787 	      snprintf (operands[op_num], 24, "16");
    788 	      continue;
    789 
    790 	    case tic6x_operand_hw_const_24:
    791 	      operands_text[op_num] = TRUE;
    792 	      snprintf (operands[op_num], 24, "24");
    793 	      continue;
    794 
    795 	    case tic6x_operand_hw_const_31:
    796 	      operands_text[op_num] = TRUE;
    797 	      snprintf (operands[op_num], 24, "31");
    798 	      continue;
    799 
    800 	    default:
    801 	      break;
    802 	    }
    803 
    804 	  for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
    805 	    {
    806 	      const tic6x_coding_field *const enc
    807 		= &opc->variable_fields[fld_num];
    808 	      const tic6x_insn_field *field;
    809 	      unsigned int fld_val;
    810 	      unsigned int reg_base = 0;
    811 	      signed int signed_fld_val;
    812               char reg_side = '?';
    813 
    814 	      if (enc->operand_num != op_num)
    815 		continue;
    816 	      field = tic6x_field_from_fmt (fmt, enc->field_id);
    817 	      if (!field)
    818 		{
    819 		  printf ("opcode %x: missing field (field_id:%d) in format\n", opcode, enc->field_id);
    820 		  abort ();
    821 		}
    822               fld_val = tic6x_field_bits (opcode, field);
    823 	      switch (enc->coding_method)
    824 		{
    825                 case tic6x_coding_cst_s3i:
    826                   (fld_val == 0x00) && (fld_val = 0x10);
    827                   (fld_val == 0x07) && (fld_val = 0x08);
    828                   /* Fall through.  */
    829 		case tic6x_coding_ucst:
    830 		case tic6x_coding_ulcst_dpr_byte:
    831 		case tic6x_coding_ulcst_dpr_half:
    832 		case tic6x_coding_ulcst_dpr_word:
    833 		case tic6x_coding_lcst_low16:
    834 		  switch (opc->operand_info[op_num].form)
    835 		    {
    836 		    case tic6x_operand_asm_const:
    837 		    case tic6x_operand_link_const:
    838 		      operands_text[op_num] = TRUE;
    839 		      snprintf (operands[op_num], 24, "%u", fld_val);
    840 		      break;
    841 
    842 		    case tic6x_operand_mem_long:
    843 		      mem_offset = fld_val;
    844 		      mem_offset_known_long = TRUE;
    845 		      break;
    846 
    847 		    default:
    848                       printf ("opcode %x: illegal operand form for operand#%d\n", opcode, op_num);
    849 		      abort ();
    850 		    }
    851 		  break;
    852 
    853 		case tic6x_coding_lcst_high16:
    854 		  operands_text[op_num] = TRUE;
    855 		  snprintf (operands[op_num], 24, "%u", fld_val << 16);
    856 		  break;
    857 
    858                 case tic6x_coding_scst_l3i:
    859 		  operands_text[op_num] = TRUE;
    860                   if (fld_val == 0)
    861 		    {
    862 		      signed_fld_val = 8;
    863 		    }
    864 		  else
    865 		    {
    866 		      signed_fld_val = (signed int) fld_val;
    867 		      signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
    868 		      signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
    869 		    }
    870 		  snprintf (operands[op_num], 24, "%d", signed_fld_val);
    871 		  break;
    872 
    873 		case tic6x_coding_scst:
    874 		  operands_text[op_num] = TRUE;
    875 		  signed_fld_val = (signed int) fld_val;
    876 		  signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
    877 		  signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
    878 		  snprintf (operands[op_num], 24, "%d", signed_fld_val);
    879 		  break;
    880 
    881 		case tic6x_coding_ucst_minus_one:
    882 		  operands_text[op_num] = TRUE;
    883 		  snprintf (operands[op_num], 24, "%u", fld_val + 1);
    884 		  break;
    885 
    886 		case tic6x_coding_pcrel:
    887 		case tic6x_coding_pcrel_half:
    888 		  signed_fld_val = (signed int) fld_val;
    889 		  signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
    890 		  signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
    891 		  if (fetch_packet_header_based
    892 		      && enc->coding_method == tic6x_coding_pcrel_half)
    893 		    signed_fld_val *= 2;
    894 		  else
    895 		    signed_fld_val *= 4;
    896 		  operands_pcrel[op_num] = TRUE;
    897 		  operands_addresses[op_num] = fp_addr + signed_fld_val;
    898 		  break;
    899 
    900 		case tic6x_coding_regpair_msb:
    901 		  if (opc->operand_info[op_num].form != tic6x_operand_regpair)
    902 		    abort ();
    903 		  operands_text[op_num] = TRUE;
    904 		  snprintf (operands[op_num], 24, "%c%u:%c%u",
    905 			    (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1),
    906 			    (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1) - 1);
    907 		  break;
    908 
    909 		case tic6x_coding_pcrel_half_unsigned:
    910 		  operands_pcrel[op_num] = TRUE;
    911 		  operands_addresses[op_num] = fp_addr + 2 * fld_val;
    912 		  break;
    913 
    914 		case tic6x_coding_reg_shift:
    915 		  fld_val <<= 1;
    916 		  /* Fall through.  */
    917 		case tic6x_coding_reg:
    918                   if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS))
    919                     {
    920 		      reg_base = 16;
    921                     }
    922 		  switch (opc->operand_info[op_num].form)
    923 		    {
    924 		    case tic6x_operand_treg:
    925                       if (!have_t)
    926 			{
    927 			  printf ("opcode %x: operand treg but missing t field\n", opcode);
    928 			  abort ();
    929 			}
    930 		      operands_text[op_num] = TRUE;
    931                       reg_side = t_val ? 'b' : 'a';
    932 		      snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
    933 		      break;
    934 
    935 		    case tic6x_operand_reg:
    936 		      operands_text[op_num] = TRUE;
    937                       reg_side = (func_unit_side == 2) ? 'b' : 'a';
    938 		      snprintf (operands[op_num], 24, "%c%u", reg_side,  reg_base + fld_val);
    939 		      break;
    940 
    941 		    case tic6x_operand_reg_nors:
    942 		      operands_text[op_num] = TRUE;
    943                       reg_side = (func_unit_side == 2) ? 'b' : 'a';
    944 		      snprintf (operands[op_num], 24, "%c%u", reg_side, fld_val);
    945 		      break;
    946 
    947 		    case tic6x_operand_reg_bside:
    948 		      operands_text[op_num] = TRUE;
    949 		      snprintf (operands[op_num], 24, "b%u", reg_base + fld_val);
    950 		      break;
    951 
    952 		    case tic6x_operand_reg_bside_nors:
    953 		      operands_text[op_num] = TRUE;
    954 		      snprintf (operands[op_num], 24, "b%u", fld_val);
    955 		      break;
    956 
    957 		    case tic6x_operand_xreg:
    958 		      operands_text[op_num] = TRUE;
    959                       reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a';
    960 		      snprintf (operands[op_num], 24, "%c%u", reg_side,  reg_base + fld_val);
    961 		      break;
    962 
    963 		    case tic6x_operand_dreg:
    964 		      operands_text[op_num] = TRUE;
    965                       reg_side = (func_unit_data_side == 2) ? 'b' : 'a';
    966 		      snprintf (operands[op_num], 24, "%c%u", reg_side,  reg_base + fld_val);
    967 		      break;
    968 
    969 		    case tic6x_operand_regpair:
    970 		      operands_text[op_num] = TRUE;
    971 		      if (fld_val & 1)
    972 			operands_ok = FALSE;
    973                       reg_side = (func_unit_side == 2) ? 'b' : 'a';
    974 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
    975                                 reg_side, reg_base + fld_val + 1,
    976 				reg_side, reg_base + fld_val);
    977 		      break;
    978 
    979 		    case tic6x_operand_xregpair:
    980 		      operands_text[op_num] = TRUE;
    981 		      if (fld_val & 1)
    982 			operands_ok = FALSE;
    983                       reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a';
    984 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
    985 				reg_side, reg_base + fld_val + 1,
    986 				reg_side, reg_base + fld_val);
    987 		      break;
    988 
    989 		    case tic6x_operand_tregpair:
    990                       if (!have_t)
    991 			{
    992 			  printf ("opcode %x: operand tregpair but missing t field\n", opcode);
    993 			  abort ();
    994 			}
    995 		      operands_text[op_num] = TRUE;
    996 		      if (fld_val & 1)
    997 			operands_ok = FALSE;
    998                       reg_side = t_val ? 'b' : 'a';
    999 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
   1000 				reg_side, reg_base + fld_val + 1,
   1001 				reg_side, reg_base + fld_val);
   1002 		      break;
   1003 
   1004 		    case tic6x_operand_dregpair:
   1005 		      operands_text[op_num] = TRUE;
   1006 		      if (fld_val & 1)
   1007 			operands_ok = FALSE;
   1008                       reg_side = (func_unit_data_side) == 2 ? 'b' : 'a';
   1009 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
   1010 				reg_side, reg_base + fld_val + 1,
   1011 				reg_side, reg_base + fld_val);
   1012 		      break;
   1013 
   1014 		    case tic6x_operand_mem_deref:
   1015 		      operands_text[op_num] = TRUE;
   1016                       reg_side = func_unit_side == 2 ? 'b' : 'a';
   1017 		      snprintf (operands[op_num], 24, "*%c%u", reg_side, reg_base + fld_val);
   1018 		      break;
   1019 
   1020 		    case tic6x_operand_mem_short:
   1021 		    case tic6x_operand_mem_ndw:
   1022 		      mem_base_reg = fld_val;
   1023 		      mem_base_reg_known = TRUE;
   1024 		      break;
   1025 
   1026 		    default:
   1027                       printf ("opcode %x: unexpected operand form %d for operand #%d",
   1028 			      opcode, opc->operand_info[op_num].form, op_num);
   1029 		      abort ();
   1030 		    }
   1031 		  break;
   1032 
   1033                 case tic6x_coding_reg_ptr:
   1034 		  switch (opc->operand_info[op_num].form)
   1035 		    {
   1036 		    case tic6x_operand_mem_short:
   1037 		    case tic6x_operand_mem_ndw:
   1038                       if (fld_val > 0x3u)
   1039 			{
   1040 			  printf("opcode %x: illegal field value for ptr register of operand #%d (%d)",
   1041 				 opcode, op_num, fld_val);
   1042 			  abort ();
   1043 			}
   1044 		      mem_base_reg = 0x4 | fld_val;
   1045 		      mem_base_reg_known = TRUE;
   1046 		      break;
   1047 
   1048 		    default:
   1049                       printf ("opcode %x: unexpected operand form %d for operand #%d",
   1050 			      opcode, opc->operand_info[op_num].form, op_num);
   1051 		      abort ();
   1052 		    }
   1053 		  break;
   1054 
   1055 		case tic6x_coding_areg:
   1056 		  switch (opc->operand_info[op_num].form)
   1057 		    {
   1058 		    case tic6x_operand_areg:
   1059 		      operands_text[op_num] = TRUE;
   1060 		      snprintf (operands[op_num], 24, "b%u",
   1061 				fld_val ? 15u : 14u);
   1062 		      break;
   1063 
   1064 		    case tic6x_operand_mem_long:
   1065 		      mem_base_reg = fld_val ? 15u : 14u;
   1066 		      mem_base_reg_known_long = TRUE;
   1067 		      break;
   1068 
   1069 		    default:
   1070                       printf ("opcode %x: bad operand form\n", opcode);
   1071 		      abort ();
   1072 		    }
   1073 		  break;
   1074 
   1075 		case tic6x_coding_mem_offset_minus_one_noscale:
   1076 		case tic6x_coding_mem_offset_minus_one:
   1077 		  fld_val += 1;
   1078 		case tic6x_coding_mem_offset_noscale:
   1079 		case tic6x_coding_mem_offset:
   1080 		  mem_offset = fld_val;
   1081 		  mem_offset_known = TRUE;
   1082 		  if (num_bits == 16)
   1083 		    {
   1084 		      mem_mode_known = TRUE;
   1085 		      mem_mode = TIC6X_INSN16_MEM_MODE_VAL (opc->flags);
   1086 		      mem_scaled_known = TRUE;
   1087 		      mem_scaled = TRUE;
   1088 		      if (opc->flags & TIC6X_FLAG_INSN16_B15PTR)
   1089 			{
   1090 			  mem_base_reg_known = TRUE;
   1091 			  mem_base_reg = 15;
   1092 			}
   1093 		      if ( enc->coding_method == tic6x_coding_mem_offset_noscale
   1094 			   || enc->coding_method == tic6x_coding_mem_offset_noscale )
   1095 			mem_scaled = FALSE;
   1096 		    }
   1097 		  break;
   1098 
   1099 		case tic6x_coding_mem_mode:
   1100 		  mem_mode = fld_val;
   1101 		  mem_mode_known = TRUE;
   1102 		  break;
   1103 
   1104 		case tic6x_coding_scaled:
   1105 		  mem_scaled = fld_val;
   1106 		  mem_scaled_known = TRUE;
   1107 		  break;
   1108 
   1109 		case tic6x_coding_crlo:
   1110 		  crlo = fld_val;
   1111 		  crlo_known = TRUE;
   1112 		  break;
   1113 
   1114 		case tic6x_coding_crhi:
   1115 		  crhi = fld_val;
   1116 		  crhi_known = TRUE;
   1117 		  break;
   1118 
   1119 		case tic6x_coding_fstg:
   1120 		case tic6x_coding_fcyc:
   1121 		  if (!prev_sploop_found)
   1122 		    {
   1123 		      bfd_vma search_fp_addr = fp_addr;
   1124 		      bfd_vma search_fp_offset = fp_offset;
   1125 		      bfd_boolean search_fp_header_based
   1126 			= fetch_packet_header_based;
   1127 		      tic6x_fetch_packet_header search_fp_header = header;
   1128 		      unsigned char search_fp[32];
   1129 		      unsigned int search_num_bits;
   1130 		      unsigned int search_opcode;
   1131 		      unsigned int sploop_ii = 0;
   1132 		      int i;
   1133 
   1134 		      memcpy (search_fp, fp, 32);
   1135 
   1136 		      /* To interpret these bits in an SPKERNEL
   1137 			 instruction, we must find the previous
   1138 			 SPLOOP-family instruction.  It may come up to
   1139 			 48 execute packets earlier.  */
   1140 		      for (i = 0; i < 48 * 8; i++)
   1141 			{
   1142 			  /* Find the previous instruction.  */
   1143 			  if (search_fp_offset & 2)
   1144 			    search_fp_offset -= 2;
   1145 			  else if (search_fp_offset >= 4)
   1146 			    {
   1147 			      if (search_fp_header_based
   1148 				  && (search_fp_header.word_compact
   1149 				      [(search_fp_offset >> 2) - 1]))
   1150 				search_fp_offset -= 2;
   1151 			      else
   1152 				search_fp_offset -= 4;
   1153 			    }
   1154 			  else
   1155 			    {
   1156 			      search_fp_addr -= 32;
   1157 			      status = info->read_memory_func (search_fp_addr,
   1158 							       search_fp,
   1159 							       32, info);
   1160 			      if (status)
   1161 				/* No previous SPLOOP instruction.  */
   1162 				break;
   1163 			      search_fp_header_based
   1164 				= (tic6x_check_fetch_packet_header
   1165 				   (search_fp, &search_fp_header, info));
   1166 			      if (search_fp_header_based)
   1167 				search_fp_offset
   1168 				  = search_fp_header.word_compact[6] ? 26 : 24;
   1169 			      else
   1170 				search_fp_offset = 28;
   1171 			    }
   1172 
   1173 			  /* Extract the previous instruction.  */
   1174 			  if (search_fp_header_based)
   1175 			    search_num_bits
   1176 			      = (search_fp_header.word_compact[search_fp_offset
   1177 							       >> 2]
   1178 				 ? 16
   1179 				 : 32);
   1180 			  else
   1181 			    search_num_bits = 32;
   1182 			  if (search_num_bits == 16)
   1183 			    {
   1184 			      if (info->endian == BFD_ENDIAN_LITTLE)
   1185 				search_opcode
   1186 				  = (tic6x_extract_16
   1187 				     (search_fp + search_fp_offset, &header, info));
   1188 			      else
   1189 				search_opcode
   1190 				  = (tic6x_extract_16
   1191 				     (search_fp + (search_fp_offset ^ 2), &header,
   1192 				      info));
   1193 			    }
   1194 			  else
   1195 			    search_opcode
   1196 			      = tic6x_extract_32 (search_fp + search_fp_offset,
   1197 						  info);
   1198 
   1199 			  /* Check whether it is an SPLOOP-family
   1200 			     instruction.  */
   1201 			  if (search_num_bits == 32
   1202 			      && ((search_opcode & 0x003ffffe) == 0x00038000
   1203 				  || (search_opcode & 0x003ffffe) == 0x0003a000
   1204 				  || ((search_opcode & 0x003ffffe)
   1205 				      == 0x0003e000)))
   1206 			    {
   1207 			      prev_sploop_found = TRUE;
   1208 			      sploop_ii = ((search_opcode >> 23) & 0x1f) + 1;
   1209 			    }
   1210 			  else if (search_num_bits == 16
   1211 				   && (search_opcode & 0x3c7e) == 0x0c66)
   1212 			    {
   1213 			      prev_sploop_found = TRUE;
   1214 			      sploop_ii
   1215 				= (((search_opcode >> 7) & 0x7)
   1216 				   | ((search_opcode >> 11) & 0x8)) + 1;
   1217 			    }
   1218 			  if (prev_sploop_found)
   1219 			    {
   1220 			      if (sploop_ii <= 0)
   1221 				{
   1222 				  printf ("opcode %x:  sloop index not found (%d)\n", opcode, sploop_ii);
   1223 				  abort ();
   1224 				}
   1225 			      else if (sploop_ii <= 1)
   1226 				fcyc_bits = 0;
   1227 			      else if (sploop_ii <= 2)
   1228 				fcyc_bits = 1;
   1229 			      else if (sploop_ii <= 4)
   1230 				fcyc_bits = 2;
   1231 			      else if (sploop_ii <= 8)
   1232 				fcyc_bits = 3;
   1233 			      else if (sploop_ii <= 14)
   1234 				fcyc_bits = 4;
   1235 			      else
   1236 				prev_sploop_found = FALSE;
   1237 			    }
   1238 			  if (prev_sploop_found)
   1239 			    break;
   1240 			}
   1241 		    }
   1242 		  if (!prev_sploop_found)
   1243 		    {
   1244 		      operands_ok = FALSE;
   1245 		      operands_text[op_num] = TRUE;
   1246 		      break;
   1247 		    }
   1248 		  if (fcyc_bits > tic6x_field_width(field))
   1249 		    {
   1250 		      printf ("opcode %x: illegal fcyc value (%d)\n", opcode, fcyc_bits);
   1251 		      abort ();
   1252 		    }
   1253 		  if (enc->coding_method == tic6x_coding_fstg)
   1254 		    {
   1255 		      int i, t;
   1256 		      for (t = 0, i = fcyc_bits; i < 6; i++)
   1257 			t = (t << 1) | ((fld_val >> i) & 1);
   1258 		      operands_text[op_num] = TRUE;
   1259 		      snprintf (operands[op_num], 24, "%u", t);
   1260 		    }
   1261 		  else
   1262 		    {
   1263 		      operands_text[op_num] = TRUE;
   1264 		      snprintf (operands[op_num], 24, "%u",
   1265 				fld_val & ((1 << fcyc_bits) - 1));
   1266 		    }
   1267 		  break;
   1268 
   1269 		case tic6x_coding_spmask:
   1270 		  if (fld_val == 0)
   1271 		    spmask_skip_operand = TRUE;
   1272 		  else
   1273 		    {
   1274 		      char *p;
   1275 		      unsigned int i;
   1276 
   1277 		      operands_text[op_num] = TRUE;
   1278 		      p = operands[op_num];
   1279 		      for (i = 0; i < 8; i++)
   1280 			if (fld_val & (1 << i))
   1281 			  {
   1282 			    *p++ = "LSDM"[i/2];
   1283 			    *p++ = '1' + (i & 1);
   1284 			    *p++ = ',';
   1285 			  }
   1286 		      p[-1] = 0;
   1287 		    }
   1288 		  break;
   1289 
   1290 		case tic6x_coding_fu:
   1291 		case tic6x_coding_data_fu:
   1292 		case tic6x_coding_xpath:
   1293 		case tic6x_coding_rside:
   1294 		  /* Don't relate to operands, so operand number is
   1295 		     meaningless.  */
   1296 		  break;
   1297 
   1298 		default:
   1299                   printf ("opcode %x: illegal field encoding (%d)\n", opcode, enc->coding_method);
   1300 		  abort ();
   1301 		}
   1302 
   1303 	      if (mem_base_reg_known_long && mem_offset_known_long)
   1304 		{
   1305 		  if (operands_text[op_num] || operands_pcrel[op_num])
   1306 		    {
   1307 		      printf ("opcode %x: long access but operands already known ?\n", opcode);
   1308 		      abort ();
   1309 		    }
   1310 		  operands_text[op_num] = TRUE;
   1311 		  snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg,
   1312 			    mem_offset * opc->operand_info[op_num].size);
   1313 		}
   1314 
   1315 	      if (mem_base_reg_known && mem_offset_known && mem_mode_known
   1316 		  && (mem_scaled_known
   1317 		      || (opc->operand_info[op_num].form
   1318 			  != tic6x_operand_mem_ndw)))
   1319 		{
   1320 		  char side;
   1321 		  char base[4];
   1322 		  bfd_boolean offset_is_reg;
   1323 		  bfd_boolean offset_scaled;
   1324 		  char offset[4];
   1325 		  char offsetp[6];
   1326 
   1327 		  if (operands_text[op_num] || operands_pcrel[op_num])
   1328 		    {
   1329 		      printf ("opcode %x: mem access operands already known ?\n", opcode);
   1330 		      abort ();
   1331 		    }
   1332 
   1333 		  side = func_unit_side == 2 ? 'b' : 'a';
   1334 		  snprintf (base, 4, "%c%u", side, mem_base_reg);
   1335 
   1336 		  offset_is_reg = ((mem_mode & 4) ? TRUE : FALSE);
   1337 		  if (offset_is_reg)
   1338 		    {
   1339 
   1340 		      if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS))
   1341 			{
   1342 			  reg_base = 16;
   1343 			}
   1344 		      snprintf (offset, 4, "%c%u", side, reg_base + mem_offset);
   1345 		      if (opc->operand_info[op_num].form
   1346 			  == tic6x_operand_mem_ndw)
   1347 			offset_scaled = mem_scaled ? TRUE : FALSE;
   1348 		      else
   1349 			offset_scaled = TRUE;
   1350 		    }
   1351 		  else
   1352 		    {
   1353 		      if (opc->operand_info[op_num].form
   1354 			  == tic6x_operand_mem_ndw)
   1355 			{
   1356 			  offset_scaled = mem_scaled ? TRUE : FALSE;
   1357 			  snprintf (offset, 4, "%u", mem_offset);
   1358 			}
   1359 		      else
   1360 			{
   1361 			  offset_scaled = FALSE;
   1362 			  snprintf (offset, 4, "%u",
   1363 				    (mem_offset
   1364 				     * opc->operand_info[op_num].size));
   1365 			}
   1366 		    }
   1367 
   1368 		  if (offset_scaled)
   1369 		    snprintf (offsetp, 6, "[%s]", offset);
   1370 		  else
   1371 		    snprintf (offsetp, 6, "(%s)", offset);
   1372 
   1373 		  operands_text[op_num] = TRUE;
   1374 		  switch (mem_mode & ~4u)
   1375 		    {
   1376 		    case 0:
   1377 		      snprintf (operands[op_num], 24, "*-%s%s", base, offsetp);
   1378 		      break;
   1379 
   1380 		    case 1:
   1381 		      snprintf (operands[op_num], 24, "*+%s%s", base, offsetp);
   1382 		      break;
   1383 
   1384 		    case 2:
   1385 		    case 3:
   1386 		      operands_ok = FALSE;
   1387 		      break;
   1388 
   1389 		    case 8:
   1390 		      snprintf (operands[op_num], 24, "*--%s%s", base,
   1391 				offsetp);
   1392 		      break;
   1393 
   1394 		    case 9:
   1395 		      snprintf (operands[op_num], 24, "*++%s%s", base,
   1396 				offsetp);
   1397 		      break;
   1398 
   1399 		    case 10:
   1400 		      snprintf (operands[op_num], 24, "*%s--%s", base,
   1401 				offsetp);
   1402 		      break;
   1403 
   1404 		    case 11:
   1405 		      snprintf (operands[op_num], 24, "*%s++%s", base,
   1406 				offsetp);
   1407 		      break;
   1408 
   1409 		    default:
   1410                       printf ("*** unknown mem_mode : %d \n", mem_mode);
   1411 		      abort ();
   1412 		    }
   1413 		}
   1414 
   1415 	      if (crlo_known && crhi_known)
   1416 		{
   1417 		  tic6x_rw rw;
   1418 		  tic6x_ctrl_id crid;
   1419 
   1420 		  if (operands_text[op_num] || operands_pcrel[op_num])
   1421 		    {
   1422 		      printf ("*** abort crlo crli\n");
   1423 		      abort ();
   1424 		    }
   1425 
   1426 		  rw = opc->operand_info[op_num].rw;
   1427 		  if (rw != tic6x_rw_read
   1428 		      && rw != tic6x_rw_write)
   1429 		    {
   1430 		      printf ("*** abort rw : %d\n", rw);
   1431 		      abort ();
   1432 		    }
   1433 
   1434 		  for (crid = 0; crid < tic6x_ctrl_max; crid++)
   1435 		    {
   1436 		      if (crlo == tic6x_ctrl_table[crid].crlo
   1437 			  && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0
   1438 			  && (rw == tic6x_rw_read
   1439 			      ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read
   1440 				 || (tic6x_ctrl_table[crid].rw
   1441 				     == tic6x_rw_read_write))
   1442 			      : (tic6x_ctrl_table[crid].rw == tic6x_rw_write
   1443 				 || (tic6x_ctrl_table[crid].rw
   1444 				     == tic6x_rw_read_write))))
   1445 			break;
   1446 		    }
   1447 		  if (crid == tic6x_ctrl_max)
   1448 		    {
   1449 		      operands_text[op_num] = TRUE;
   1450 		      operands_ok = FALSE;
   1451 		    }
   1452 		  else
   1453 		    {
   1454 		      operands_text[op_num] = TRUE;
   1455 		      snprintf (operands[op_num], 24, "%s",
   1456 				tic6x_ctrl_table[crid].name);
   1457 		    }
   1458 		}
   1459 
   1460 	      if (operands_text[op_num] || operands_pcrel[op_num]
   1461 		  || spmask_skip_operand)
   1462 		break;
   1463 	    }
   1464           /* end for fld_num */
   1465 
   1466 	  if (spmask_skip_operand)
   1467 	    {
   1468 	      /* SPMASK operands are only valid as the single operand
   1469 		 in the opcode table.  */
   1470 	      if (num_operands != 1)
   1471 		{
   1472 		  printf ("opcode: %x, num_operands != 1 : %d\n", opcode, num_operands);
   1473 		  abort ();
   1474 		}
   1475 	      num_operands = 0;
   1476 	      break;
   1477 	    }
   1478 
   1479 	  /* The operand must by now have been decoded.  */
   1480 	  if (!operands_text[op_num] && !operands_pcrel[op_num])
   1481             {
   1482               printf ("opcode: %x, operand #%d not decoded\n", opcode, op_num);
   1483               abort ();
   1484             }
   1485         }
   1486       /* end for op_num */
   1487 
   1488       if (!operands_ok)
   1489 	continue;
   1490 
   1491       info->bytes_per_chunk = num_bits / 8;
   1492       info->fprintf_func (info->stream, "%s", parallel);
   1493       info->fprintf_func (info->stream, "%s%s%s", cond, opc->name,
   1494                           func_unit);
   1495       for (op_num = 0; op_num < num_operands; op_num++)
   1496 	{
   1497 	  info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ','));
   1498 	  if (operands_pcrel[op_num])
   1499 	    info->print_address_func (operands_addresses[op_num], info);
   1500 	  else
   1501 	    info->fprintf_func (info->stream, "%s", operands[op_num]);
   1502 	}
   1503       if (fetch_packet_header_based && header.prot)
   1504 	info->fprintf_func (info->stream, " || nop 5");
   1505 
   1506       return num_bits / 8;
   1507     }
   1508 
   1509   info->bytes_per_chunk = num_bits / 8;
   1510   info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>",
   1511 		      (int) num_bits / 4, opcode);
   1512   return num_bits / 8;
   1513 }
   1514