tic6x-dis.c revision 1.1.1.3
1/* TI C6X disassembler.
2   Copyright (C) 2010-2016 Free Software Foundation, Inc.
3   Contributed by Joseph Myers <joseph@codesourcery.com>
4   		  Bernd Schmidt  <bernds@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.  */
29const 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.  */
38const 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.  */
53const 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
113const tic6x_insn_field *
114tic6x_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
127static unsigned int
128tic6x_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
144static unsigned int
145tic6x_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
162static unsigned int
163tic6x_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
173static unsigned int
174tic6x_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
192static bfd_boolean
193tic6x_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
236int
237print_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