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