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