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