1/* TI C6X disassembler.
2   Copyright (C) 2010-2022 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 "disassemble.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) | ((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
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 bool
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))) != 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
235int
236print_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