1 /* TI C6X disassembler.
2    Copyright 2010
3    Free Software Foundation, Inc.
4    Contributed by Joseph Myers <joseph@codesourcery.com>
5    		  Bernd Schmidt  <bernds@codesourcery.com>
6 
7    This file is part of libopcodes.
8 
9    This library is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    It is distributed in the hope that it will be useful, but WITHOUT
15    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17    License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22    MA 02110-1301, USA.  */
23 
24 #include "sysdep.h"
25 #include "dis-asm.h"
26 #include "opcode/tic6x.h"
27 #include "libiberty.h"
28 
29 /* Define the instruction format table.  */
30 const tic6x_insn_format tic6x_insn_format_table[tic6x_insn_format_max] =
31   {
32 #define FMT(name, num_bits, cst_bits, mask, fields) \
33     { num_bits, cst_bits, mask, fields },
34 #include "opcode/tic6x-insn-formats.h"
35 #undef FMT
36   };
37 
38 /* Define the control register table.  */
39 const tic6x_ctrl tic6x_ctrl_table[tic6x_ctrl_max] =
40   {
41 #define CTRL(name, isa, rw, crlo, crhi_mask)	\
42     {						\
43       STRINGX(name),				\
44       CONCAT2(TIC6X_INSN_,isa),			\
45       CONCAT2(tic6x_rw_,rw),			\
46       crlo,					\
47       crhi_mask					\
48     },
49 #include "opcode/tic6x-control-registers.h"
50 #undef CTRL
51   };
52 
53 /* Define the opcode table.  */
54 const tic6x_opcode tic6x_opcode_table[tic6x_opcode_max] =
55   {
56 #define INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \
57     {									\
58       STRINGX(name),							\
59       CONCAT2(tic6x_func_unit_,func_unit),				\
60       CONCAT4(tic6x_insn_format_,func_unit,_,format),			\
61       CONCAT2(tic6x_pipeline_,type),					\
62       CONCAT2(TIC6X_INSN_,isa),						\
63       flags,								\
64       fixed,								\
65       ops,								\
66       var								\
67     },
68 #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
69     {									\
70       STRINGX(name),							\
71       CONCAT2(tic6x_func_unit_,func_unit),				\
72       CONCAT4(tic6x_insn_format_,func_unit,_,format),			\
73       CONCAT2(tic6x_pipeline_,type),					\
74       CONCAT2(TIC6X_INSN_,isa),						\
75       flags,								\
76       fixed,								\
77       ops,								\
78       var								\
79     },
80 #include "opcode/tic6x-opcode-table.h"
81 #undef INSN
82 #undef INSNE
83   };
84 
85 /* If instruction format FMT has a field FIELD, return a pointer to
86    the description of that field; otherwise return NULL.  */
87 
88 const tic6x_insn_field *
tic6x_field_from_fmt(const tic6x_insn_format * fmt,tic6x_insn_field_id field)89 tic6x_field_from_fmt (const tic6x_insn_format *fmt, tic6x_insn_field_id field)
90 {
91   unsigned int f;
92 
93   for (f = 0; f < fmt->num_fields; f++)
94     if (fmt->fields[f].field_id == field)
95       return &fmt->fields[f];
96 
97   return NULL;
98 }
99 
100 /* Extract the bits corresponding to FIELD from OPCODE.  */
101 
102 static unsigned int
tic6x_field_bits(unsigned int opcode,const tic6x_insn_field * field)103 tic6x_field_bits (unsigned int opcode, const tic6x_insn_field *field)
104 {
105   return (opcode >> field->low_pos) & ((1u << field->width) - 1);
106 }
107 
108 /* Extract a 32-bit value read from the instruction stream.  */
109 
110 static unsigned int
tic6x_extract_32(unsigned char * p,struct disassemble_info * info)111 tic6x_extract_32 (unsigned char *p, struct disassemble_info *info)
112 {
113   if (info->endian == BFD_ENDIAN_LITTLE)
114     return (p[0]) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
115   else
116     return (p[3]) | (p[2] << 8) | (p[1] << 16) | (p[0] << 24);
117 }
118 
119 /* Extract a 16-bit value read from the instruction stream.  */
120 
121 static unsigned int
tic6x_extract_16(unsigned char * p,struct disassemble_info * info)122 tic6x_extract_16 (unsigned char *p, struct disassemble_info *info)
123 {
124   if (info->endian == BFD_ENDIAN_LITTLE)
125     return (p[0]) | (p[1] << 8);
126   else
127     return (p[1]) | (p[0] << 8);
128 }
129 
130 /* FP points to a fetch packet.  Return whether it is header-based; if
131    it is, fill in HEADER.  */
132 
133 static bfd_boolean
tic6x_check_fetch_packet_header(unsigned char * fp,tic6x_fetch_packet_header * header,struct disassemble_info * info)134 tic6x_check_fetch_packet_header (unsigned char *fp,
135 				 tic6x_fetch_packet_header *header,
136 				 struct disassemble_info *info)
137 {
138   int i;
139 
140   header->header = tic6x_extract_32 (fp + 28, info);
141   if ((header->header & 0xf0000000) != 0xe0000000)
142     return FALSE;
143 
144   for (i = 0; i < 7; i++)
145     header->word_compact[i]
146       = (header->header & (1u << (21 + i))) ? TRUE : FALSE;
147 
148   header->prot = (header->header & (1u << 20)) ? TRUE : FALSE;
149   header->rs = (header->header & (1u << 19)) ? TRUE : FALSE;
150   header->dsz = (header->header >> 16) & 0x7;
151   header->br = (header->header & (1u << 15)) ? TRUE : FALSE;
152   header->sat = (header->header & (1u << 14)) ? TRUE : FALSE;
153 
154   for (i = 0; i < 14; i++)
155     header->p_bits[i]
156       = (header->header & (1u << i)) ? TRUE : FALSE;
157 
158   return TRUE;
159 }
160 
161 /* Disassemble the instruction at ADDR and print it using
162    INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes
163    consumed.  */
164 
165 int
print_insn_tic6x(bfd_vma addr,struct disassemble_info * info)166 print_insn_tic6x (bfd_vma addr, struct disassemble_info *info)
167 {
168   int status;
169   bfd_vma fp_addr;
170   bfd_vma fp_offset;
171   unsigned char fp[32];
172   unsigned int opcode;
173   tic6x_opcode_id opcode_id;
174   bfd_boolean fetch_packet_header_based;
175   tic6x_fetch_packet_header header;
176   unsigned int num_bits;
177   bfd_boolean bad_offset = FALSE;
178 
179   fp_offset = addr & 0x1f;
180   fp_addr = addr - fp_offset;
181   status = info->read_memory_func (fp_addr, fp, 32, info);
182   if (status)
183     {
184       info->memory_error_func (status, addr, info);
185       return -1;
186     }
187 
188   fetch_packet_header_based
189     = tic6x_check_fetch_packet_header (fp, &header, info);
190   if (fetch_packet_header_based)
191     {
192       if (fp_offset & 0x1)
193 	bad_offset = TRUE;
194       if ((fp_offset & 0x3) && (fp_offset >= 28
195 				|| !header.word_compact[fp_offset >> 2]))
196 	bad_offset = TRUE;
197       if (fp_offset == 28)
198 	{
199 	  info->bytes_per_chunk = 4;
200 	  info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>",
201 			      header.header);
202 	  return 4;
203 	}
204       num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32);
205     }
206   else
207     {
208       num_bits = 32;
209       if (fp_offset & 0x3)
210 	bad_offset = TRUE;
211     }
212 
213   if (bad_offset)
214     {
215       info->bytes_per_chunk = 1;
216       info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]);
217       return 1;
218     }
219 
220   if (num_bits == 16)
221     {
222       /* The least-significant part of a 32-bit word comes logically
223 	 before the most-significant part.  For big-endian, follow the
224 	 TI assembler in showing instructions in logical order by
225 	 pretending that the two halves of the word are in opposite
226 	 locations to where they actually are.  */
227       if (info->endian == BFD_ENDIAN_LITTLE)
228 	opcode = tic6x_extract_16 (fp + fp_offset, info);
229       else
230 	opcode = tic6x_extract_16 (fp + (fp_offset ^ 2), info);
231     }
232   else
233     opcode = tic6x_extract_32 (fp + fp_offset, info);
234 
235   for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++)
236     {
237       const tic6x_opcode *const opc = &tic6x_opcode_table[opcode_id];
238       const tic6x_insn_format *const fmt
239 	= &tic6x_insn_format_table[opc->format];
240       const tic6x_insn_field *creg_field;
241       bfd_boolean p_bit;
242       const char *parallel;
243       const char *cond = "";
244       const char *func_unit;
245       char func_unit_buf[7];
246       unsigned int func_unit_side = 0;
247       unsigned int func_unit_data_side = 0;
248       unsigned int func_unit_cross = 0;
249       /* The maximum length of the text of a non-PC-relative operand
250 	 is 24 bytes (SPMASK masking all eight functional units, with
251 	 separating commas and trailing NUL).  */
252       char operands[TIC6X_MAX_OPERANDS][24] = { { 0 } };
253       bfd_vma operands_addresses[TIC6X_MAX_OPERANDS] = { 0 };
254       bfd_boolean operands_text[TIC6X_MAX_OPERANDS] = { FALSE };
255       bfd_boolean operands_pcrel[TIC6X_MAX_OPERANDS] = { FALSE };
256       unsigned int fix;
257       unsigned int num_operands;
258       unsigned int op_num;
259       bfd_boolean fixed_ok;
260       bfd_boolean operands_ok;
261 
262       if (opc->flags & TIC6X_FLAG_MACRO)
263 	continue;
264       if (fmt->num_bits != num_bits)
265 	continue;
266       if ((opcode & fmt->mask) != fmt->cst_bits)
267 	continue;
268 
269       /* If the format has a creg field, it is only a candidate for a
270 	 match if the creg and z fields have values indicating a valid
271 	 condition; reserved values indicate either an instruction
272 	 format without a creg field, or an invalid instruction.  */
273       creg_field = tic6x_field_from_fmt (fmt, tic6x_field_creg);
274       if (creg_field)
275 	{
276 	  const tic6x_insn_field *z_field;
277 	  unsigned int creg_value, z_value;
278 	  static const char *const conds[8][2] =
279 	    {
280 	      { "", NULL },
281 	      { "[b0] ", "[!b0] " },
282 	      { "[b1] ", "[!b1] " },
283 	      { "[b2] ", "[!b2] " },
284 	      { "[a1] ", "[!a1] " },
285 	      { "[a2] ", "[!a2] " },
286 	      { "[a0] ", "[!a0] " },
287 	      { NULL, NULL }
288 	    };
289 
290 	  /* A creg field is not meaningful without a z field, so if
291 	     the z field is not present this is an error in the format
292 	     table.  */
293 	  z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
294 	  if (!z_field)
295 	    abort ();
296 
297 	  creg_value = tic6x_field_bits (opcode, creg_field);
298 	  z_value = tic6x_field_bits (opcode, z_field);
299 	  cond = conds[creg_value][z_value];
300 	  if (cond == NULL)
301 	    continue;
302 	}
303 
304       /* All fixed fields must have matching values; all fields with
305 	 restricted ranges must have values within those ranges.  */
306       fixed_ok = TRUE;
307       for (fix = 0; fix < opc->num_fixed_fields; fix++)
308 	{
309 	  unsigned int field_bits;
310 	  const tic6x_insn_field *const field
311 	    = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id);
312 
313 	  if (!field)
314 	    abort ();
315 	  field_bits = tic6x_field_bits (opcode, field);
316 	  if (field_bits < opc->fixed_fields[fix].min_val
317 	      || field_bits > opc->fixed_fields[fix].max_val)
318 	    {
319 	      fixed_ok = FALSE;
320 	      break;
321 	    }
322 	}
323       if (!fixed_ok)
324 	continue;
325 
326       /* The instruction matches.  */
327 
328       /* The p-bit indicates whether this instruction is in parallel
329 	 with the *next* instruction, whereas the parallel bars
330 	 indicate the instruction is in parallel with the *previous*
331 	 instruction.  Thus, we must find the p-bit for the previous
332 	 instruction.  */
333       if (num_bits == 16 && (fp_offset & 0x2) == 2)
334 	{
335 	  /* This is the logically second (most significant; second in
336 	     fp_offset terms because fp_offset relates to logical not
337 	     physical addresses) instruction of a compact pair; find
338 	     the p-bit for the first (least significant).  */
339 	  p_bit = header.p_bits[(fp_offset >> 2) << 1];
340 	}
341       else if (fp_offset >= 4)
342 	{
343 	  /* Find the last instruction of the previous word in this
344 	     fetch packet.  For compact instructions, this is the most
345 	     significant 16 bits.  */
346 	  if (fetch_packet_header_based
347 	      && header.word_compact[(fp_offset >> 2) - 1])
348 	    p_bit = header.p_bits[(fp_offset >> 1) - 1];
349 	  else
350 	    {
351 	      unsigned int prev_opcode
352 		= tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info);
353 	      p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
354 	    }
355 	}
356       else
357 	{
358 	  /* Find the last instruction of the previous fetch
359 	     packet.  */
360 	  unsigned char fp_prev[32];
361 	  status = info->read_memory_func (fp_addr - 32, fp_prev, 32, info);
362 	  if (status)
363 	    /* No previous instruction to be parallel with.  */
364 	    p_bit = FALSE;
365 	  else
366 	    {
367 	      bfd_boolean prev_header_based;
368 	      tic6x_fetch_packet_header prev_header;
369 
370 	      prev_header_based
371 		= tic6x_check_fetch_packet_header (fp_prev, &prev_header, info);
372 	      if (prev_header_based && prev_header.word_compact[6])
373 		p_bit = prev_header.p_bits[13];
374 	      else
375 		{
376 		  unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28,
377 							       info);
378 		  p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
379 		}
380 	    }
381 	}
382       parallel = p_bit ? "|| " : "";
383 
384       if (opc->func_unit == tic6x_func_unit_nfu)
385 	func_unit = "";
386       else
387 	{
388 	  unsigned int fld_num;
389 	  char func_unit_char;
390 	  const char *data_str;
391 	  bfd_boolean have_areg = FALSE;
392 	  bfd_boolean have_cross = FALSE;
393 
394 	  func_unit_side = (opc->flags & TIC6X_FLAG_SIDE_B_ONLY) ? 2 : 0;
395 	  func_unit_cross = 0;
396 	  func_unit_data_side = (opc->flags & TIC6X_FLAG_SIDE_T2_ONLY) ? 2 : 0;
397 
398 	  for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
399 	    {
400 	      const tic6x_coding_field *const enc = &opc->variable_fields[fld_num];
401 	      const tic6x_insn_field *field;
402 	      unsigned int fld_val;
403 
404 	      field = tic6x_field_from_fmt (fmt, enc->field_id);
405 	      if (!field)
406 		abort ();
407 	      fld_val = tic6x_field_bits (opcode, field);
408 	      switch (enc->coding_method)
409 		{
410 		case tic6x_coding_fu:
411 		  /* The side must be specified exactly once.  */
412 		  if (func_unit_side)
413 		    abort ();
414 		  func_unit_side = (fld_val ? 2 : 1);
415 		  break;
416 
417 		case tic6x_coding_data_fu:
418 		  /* The data side must be specified exactly once.  */
419 		  if (func_unit_data_side)
420 		    abort ();
421 		  func_unit_data_side = (fld_val ? 2 : 1);
422 		  break;
423 
424 		case tic6x_coding_xpath:
425 		  /* Cross path use must be specified exactly
426 		     once.  */
427 		  if (have_cross)
428 		    abort ();
429 		  have_cross = TRUE;
430 		  func_unit_cross = fld_val;
431 		  break;
432 
433 		case tic6x_coding_areg:
434 		  have_areg = TRUE;
435 		  break;
436 
437 		default:
438 		  /* Don't relate to functional units.  */
439 		  break;
440 		}
441 	    }
442 
443 	  /* The side of the functional unit used must now have been
444 	     determined either from the flags or from an instruction
445 	     field.  */
446 	  if (func_unit_side != 1 && func_unit_side != 2)
447 	    abort ();
448 
449 	  /* Cross paths are not applicable when sides are specified
450 	     for both address and data paths.  */
451 	  if (func_unit_data_side && have_cross)
452 	    abort ();
453 
454 	  /* Separate address and data paths are only applicable for
455 	     the D unit.  */
456 	  if (func_unit_data_side && opc->func_unit != tic6x_func_unit_d)
457 	    abort ();
458 
459 	  /* If an address register is being used but in ADDA rather
460 	     than a load or store, it uses a cross path for side-A
461 	     instructions, and the cross path use is not specified by
462 	     an instruction field.  */
463 	  if (have_areg && !func_unit_data_side)
464 	    {
465 	      if (have_cross)
466 		abort ();
467 	      func_unit_cross = (func_unit_side == 1 ? TRUE : FALSE);
468 	    }
469 
470 	  switch (opc->func_unit)
471 	    {
472 	    case tic6x_func_unit_d:
473 	      func_unit_char = 'D';
474 	      break;
475 
476 	    case tic6x_func_unit_l:
477 	      func_unit_char = 'L';
478 	      break;
479 
480 	    case tic6x_func_unit_m:
481 	      func_unit_char = 'M';
482 	      break;
483 
484 	    case tic6x_func_unit_s:
485 	      func_unit_char = 'S';
486 	      break;
487 
488 	    default:
489 	      abort ();
490 	    }
491 
492 	  switch (func_unit_data_side)
493 	    {
494 	    case 0:
495 	      data_str = "";
496 	      break;
497 
498 	    case 1:
499 	      data_str = "T1";
500 	      break;
501 
502 	    case 2:
503 	      data_str = "T2";
504 	      break;
505 
506 	    default:
507 	      abort ();
508 	    }
509 
510 	  snprintf (func_unit_buf, 7, " .%c%u%s%s", func_unit_char,
511 		    func_unit_side, (func_unit_cross ? "X" : ""), data_str);
512 	  func_unit = func_unit_buf;
513 	}
514 
515       /* For each operand there must be one or more fields set based
516 	 on that operand, that can together be used to derive the
517 	 operand value.  */
518       operands_ok = TRUE;
519       num_operands = opc->num_operands;
520       for (op_num = 0; op_num < num_operands; op_num++)
521 	{
522 	  unsigned int fld_num;
523 	  unsigned int mem_base_reg = 0;
524 	  bfd_boolean mem_base_reg_known = FALSE;
525 	  bfd_boolean mem_base_reg_known_long = FALSE;
526 	  unsigned int mem_offset = 0;
527 	  bfd_boolean mem_offset_known = FALSE;
528 	  bfd_boolean mem_offset_known_long = FALSE;
529 	  unsigned int mem_mode = 0;
530 	  bfd_boolean mem_mode_known = FALSE;
531 	  unsigned int mem_scaled = 0;
532 	  bfd_boolean mem_scaled_known = FALSE;
533 	  unsigned int crlo = 0;
534 	  bfd_boolean crlo_known = FALSE;
535 	  unsigned int crhi = 0;
536 	  bfd_boolean crhi_known = FALSE;
537 	  bfd_boolean spmask_skip_operand = FALSE;
538 	  unsigned int fcyc_bits = 0;
539 	  bfd_boolean prev_sploop_found = FALSE;
540 
541 	  switch (opc->operand_info[op_num].form)
542 	    {
543 	    case tic6x_operand_retreg:
544 	      /* Fully determined by the functional unit.  */
545 	      operands_text[op_num] = TRUE;
546 	      snprintf (operands[op_num], 24, "%c3",
547 			(func_unit_side == 2 ? 'b' : 'a'));
548 	      continue;
549 
550 	    case tic6x_operand_irp:
551 	      operands_text[op_num] = TRUE;
552 	      snprintf (operands[op_num], 24, "irp");
553 	      continue;
554 
555 	    case tic6x_operand_nrp:
556 	      operands_text[op_num] = TRUE;
557 	      snprintf (operands[op_num], 24, "nrp");
558 	      continue;
559 
560 	    default:
561 	      break;
562 	    }
563 
564 	  for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
565 	    {
566 	      const tic6x_coding_field *const enc
567 		= &opc->variable_fields[fld_num];
568 	      const tic6x_insn_field *field;
569 	      unsigned int fld_val;
570 	      signed int signed_fld_val;
571 
572 	      if (enc->operand_num != op_num)
573 		continue;
574 	      field = tic6x_field_from_fmt (fmt, enc->field_id);
575 	      if (!field)
576 		abort ();
577 	      fld_val = tic6x_field_bits (opcode, field);
578 	      switch (enc->coding_method)
579 		{
580 		case tic6x_coding_ucst:
581 		case tic6x_coding_ulcst_dpr_byte:
582 		case tic6x_coding_ulcst_dpr_half:
583 		case tic6x_coding_ulcst_dpr_word:
584 		case tic6x_coding_lcst_low16:
585 		  switch (opc->operand_info[op_num].form)
586 		    {
587 		    case tic6x_operand_asm_const:
588 		    case tic6x_operand_link_const:
589 		      operands_text[op_num] = TRUE;
590 		      snprintf (operands[op_num], 24, "%u", fld_val);
591 		      break;
592 
593 		    case tic6x_operand_mem_long:
594 		      mem_offset = fld_val;
595 		      mem_offset_known_long = TRUE;
596 		      break;
597 
598 		    default:
599 		      abort ();
600 		    }
601 		  break;
602 
603 		case tic6x_coding_lcst_high16:
604 		  operands_text[op_num] = TRUE;
605 		  snprintf (operands[op_num], 24, "%u", fld_val << 16);
606 		  break;
607 
608 		case tic6x_coding_scst:
609 		  operands_text[op_num] = TRUE;
610 		  signed_fld_val = (signed int) fld_val;
611 		  signed_fld_val ^= (1 << (field->width - 1));
612 		  signed_fld_val -= (1 << (field->width - 1));
613 		  snprintf (operands[op_num], 24, "%d", signed_fld_val);
614 		  break;
615 
616 		case tic6x_coding_ucst_minus_one:
617 		  operands_text[op_num] = TRUE;
618 		  snprintf (operands[op_num], 24, "%u", fld_val + 1);
619 		  break;
620 
621 		case tic6x_coding_pcrel:
622 		case tic6x_coding_pcrel_half:
623 		  signed_fld_val = (signed int) fld_val;
624 		  signed_fld_val ^= (1 << (field->width - 1));
625 		  signed_fld_val -= (1 << (field->width - 1));
626 		  if (fetch_packet_header_based
627 		      && enc->coding_method == tic6x_coding_pcrel_half)
628 		    signed_fld_val *= 2;
629 		  else
630 		    signed_fld_val *= 4;
631 		  operands_pcrel[op_num] = TRUE;
632 		  operands_addresses[op_num] = fp_addr + signed_fld_val;
633 		  break;
634 
635 		case tic6x_coding_reg_shift:
636 		  fld_val <<= 1;
637 		  /* Fall through.  */
638 		case tic6x_coding_reg:
639 		  switch (opc->operand_info[op_num].form)
640 		    {
641 		    case tic6x_operand_reg:
642 		      operands_text[op_num] = TRUE;
643 		      snprintf (operands[op_num], 24, "%c%u",
644 				(func_unit_side == 2 ? 'b' : 'a'), fld_val);
645 		      break;
646 
647 		    case tic6x_operand_xreg:
648 		      operands_text[op_num] = TRUE;
649 		      snprintf (operands[op_num], 24, "%c%u",
650 				(((func_unit_side == 2) ^ func_unit_cross)
651 				 ? 'b'
652 				 : 'a'), fld_val);
653 		      break;
654 
655 		    case tic6x_operand_dreg:
656 		      operands_text[op_num] = TRUE;
657 		      snprintf (operands[op_num], 24, "%c%u",
658 				(func_unit_data_side == 2 ? 'b' : 'a'),
659 				fld_val);
660 		      break;
661 
662 		    case tic6x_operand_regpair:
663 		      operands_text[op_num] = TRUE;
664 		      if (fld_val & 1)
665 			operands_ok = FALSE;
666 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
667 				(func_unit_side == 2 ? 'b' : 'a'), fld_val + 1,
668 				(func_unit_side == 2 ? 'b' : 'a'), fld_val);
669 		      break;
670 
671 		    case tic6x_operand_xregpair:
672 		      operands_text[op_num] = TRUE;
673 		      if (fld_val & 1)
674 			operands_ok = FALSE;
675 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
676 				(((func_unit_side == 2) ^ func_unit_cross)
677 				 ? 'b'
678 				 : 'a'), fld_val + 1,
679 				(((func_unit_side == 2) ^ func_unit_cross)
680 				 ? 'b'
681 				 : 'a'), fld_val);
682 		      break;
683 
684 		    case tic6x_operand_dregpair:
685 		      operands_text[op_num] = TRUE;
686 		      if (fld_val & 1)
687 			operands_ok = FALSE;
688 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
689 				(func_unit_data_side == 2 ? 'b' : 'a'),
690 				fld_val + 1,
691 				(func_unit_data_side == 2 ? 'b' : 'a'),
692 				fld_val);
693 		      break;
694 
695 		    case tic6x_operand_mem_deref:
696 		      operands_text[op_num] = TRUE;
697 		      snprintf (operands[op_num], 24, "*%c%u",
698 				(func_unit_side == 2 ? 'b' : 'a'), fld_val);
699 		      break;
700 
701 		    case tic6x_operand_mem_short:
702 		    case tic6x_operand_mem_ndw:
703 		      mem_base_reg = fld_val;
704 		      mem_base_reg_known = TRUE;
705 		      break;
706 
707 		    default:
708 		      abort ();
709 		    }
710 		  break;
711 
712 		case tic6x_coding_areg:
713 		  switch (opc->operand_info[op_num].form)
714 		    {
715 		    case tic6x_operand_areg:
716 		      operands_text[op_num] = TRUE;
717 		      snprintf (operands[op_num], 24, "b%u",
718 				fld_val ? 15u : 14u);
719 		      break;
720 
721 		    case tic6x_operand_mem_long:
722 		      mem_base_reg = fld_val ? 15u : 14u;
723 		      mem_base_reg_known_long = TRUE;
724 		      break;
725 
726 		    default:
727 		      abort ();
728 		    }
729 		  break;
730 
731 		case tic6x_coding_mem_offset:
732 		case tic6x_coding_mem_offset_noscale:
733 		  mem_offset = fld_val;
734 		  mem_offset_known = TRUE;
735 		  break;
736 
737 		case tic6x_coding_mem_mode:
738 		  mem_mode = fld_val;
739 		  mem_mode_known = TRUE;
740 		  break;
741 
742 		case tic6x_coding_scaled:
743 		  mem_scaled = fld_val;
744 		  mem_scaled_known = TRUE;
745 		  break;
746 
747 		case tic6x_coding_crlo:
748 		  crlo = fld_val;
749 		  crlo_known = TRUE;
750 		  break;
751 
752 		case tic6x_coding_crhi:
753 		  crhi = fld_val;
754 		  crhi_known = TRUE;
755 		  break;
756 
757 		case tic6x_coding_fstg:
758 		case tic6x_coding_fcyc:
759 		  if (!prev_sploop_found)
760 		    {
761 		      bfd_vma search_fp_addr = fp_addr;
762 		      bfd_vma search_fp_offset = fp_offset;
763 		      bfd_boolean search_fp_header_based
764 			= fetch_packet_header_based;
765 		      tic6x_fetch_packet_header search_fp_header = header;
766 		      unsigned char search_fp[32];
767 		      unsigned int search_num_bits;
768 		      unsigned int search_opcode;
769 		      unsigned int sploop_ii = 0;
770 		      int i;
771 
772 		      memcpy (search_fp, fp, 32);
773 
774 		      /* To interpret these bits in an SPKERNEL
775 			 instruction, we must find the previous
776 			 SPLOOP-family instruction.  It may come up to
777 			 48 execute packets earlier.  */
778 		      for (i = 0; i < 48 * 8; i++)
779 			{
780 			  /* Find the previous instruction.  */
781 			  if (search_fp_offset & 2)
782 			    search_fp_offset -= 2;
783 			  else if (search_fp_offset >= 4)
784 			    {
785 			      if (search_fp_header_based
786 				  && (search_fp_header.word_compact
787 				      [(search_fp_offset >> 2) - 1]))
788 				search_fp_offset -= 2;
789 			      else
790 				search_fp_offset -= 4;
791 			    }
792 			  else
793 			    {
794 			      search_fp_addr -= 32;
795 			      status = info->read_memory_func (search_fp_addr,
796 							       search_fp,
797 							       32, info);
798 			      if (status)
799 				/* No previous SPLOOP instruction.  */
800 				break;
801 			      search_fp_header_based
802 				= (tic6x_check_fetch_packet_header
803 				   (search_fp, &search_fp_header, info));
804 			      if (search_fp_header_based)
805 				search_fp_offset
806 				  = search_fp_header.word_compact[6] ? 26 : 24;
807 			      else
808 				search_fp_offset = 28;
809 			    }
810 
811 			  /* Extract the previous instruction.  */
812 			  if (search_fp_header_based)
813 			    search_num_bits
814 			      = (search_fp_header.word_compact[search_fp_offset
815 							       >> 2]
816 				 ? 16
817 				 : 32);
818 			  else
819 			    search_num_bits = 32;
820 			  if (search_num_bits == 16)
821 			    {
822 			      if (info->endian == BFD_ENDIAN_LITTLE)
823 				search_opcode
824 				  = (tic6x_extract_16
825 				     (search_fp + search_fp_offset, info));
826 			      else
827 				search_opcode
828 				  = (tic6x_extract_16
829 				     (search_fp + (search_fp_offset ^ 2),
830 				      info));
831 			    }
832 			  else
833 			    search_opcode
834 			      = tic6x_extract_32 (search_fp + search_fp_offset,
835 						  info);
836 
837 			  /* Check whether it is an SPLOOP-family
838 			     instruction.  */
839 			  if (search_num_bits == 32
840 			      && ((search_opcode & 0x003ffffe) == 0x00038000
841 				  || (search_opcode & 0x003ffffe) == 0x0003a000
842 				  || ((search_opcode & 0x003ffffe)
843 				      == 0x0003e000)))
844 			    {
845 			      prev_sploop_found = TRUE;
846 			      sploop_ii = ((search_opcode >> 23) & 0x1f) + 1;
847 			    }
848 			  else if (search_num_bits == 16
849 				   && (search_opcode & 0x3c7e) == 0x0c66)
850 			    {
851 			      prev_sploop_found = TRUE;
852 			      sploop_ii
853 				= (((search_opcode >> 7) & 0x7)
854 				   | ((search_opcode >> 11) & 0x8)) + 1;
855 			    }
856 			  if (prev_sploop_found)
857 			    {
858 			      if (sploop_ii <= 0)
859 				abort ();
860 			      else if (sploop_ii <= 1)
861 				fcyc_bits = 0;
862 			      else if (sploop_ii <= 2)
863 				fcyc_bits = 1;
864 			      else if (sploop_ii <= 4)
865 				fcyc_bits = 2;
866 			      else if (sploop_ii <= 8)
867 				fcyc_bits = 3;
868 			      else if (sploop_ii <= 14)
869 				fcyc_bits = 4;
870 			      else
871 				prev_sploop_found = FALSE;
872 			    }
873 			  if (prev_sploop_found)
874 			    break;
875 			}
876 		    }
877 		  if (!prev_sploop_found)
878 		    {
879 		      operands_ok = FALSE;
880 		      operands_text[op_num] = TRUE;
881 		      break;
882 		    }
883 		  if (fcyc_bits > field->width)
884 		    abort ();
885 		  if (enc->coding_method == tic6x_coding_fstg)
886 		    {
887 		      int i, t;
888 		      for (t = 0, i = fcyc_bits; i < 6; i++)
889 			t = (t << 1) | ((fld_val >> i) & 1);
890 		      operands_text[op_num] = TRUE;
891 		      snprintf (operands[op_num], 24, "%u", t);
892 		    }
893 		  else
894 		    {
895 		      operands_text[op_num] = TRUE;
896 		      snprintf (operands[op_num], 24, "%u",
897 				fld_val & ((1 << fcyc_bits) - 1));
898 		    }
899 		  break;
900 
901 		case tic6x_coding_spmask:
902 		  if (fld_val == 0)
903 		    spmask_skip_operand = TRUE;
904 		  else
905 		    {
906 		      char *p;
907 		      unsigned int i;
908 
909 		      operands_text[op_num] = TRUE;
910 		      p = operands[op_num];
911 		      for (i = 0; i < 8; i++)
912 			if (fld_val & (1 << i))
913 			  {
914 			    *p++ = "LSDM"[i/2];
915 			    *p++ = '1' + (i & 1);
916 			    *p++ = ',';
917 			  }
918 		      p[-1] = 0;
919 		    }
920 		  break;
921 
922 		case tic6x_coding_fu:
923 		case tic6x_coding_data_fu:
924 		case tic6x_coding_xpath:
925 		  /* Don't relate to operands, so operand number is
926 		     meaningless.  */
927 		  break;
928 
929 		default:
930 		  abort ();
931 		}
932 
933 	      if (mem_base_reg_known_long && mem_offset_known_long)
934 		{
935 		  if (operands_text[op_num] || operands_pcrel[op_num])
936 		    abort ();
937 		  operands_text[op_num] = TRUE;
938 		  snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg,
939 			    mem_offset * opc->operand_info[op_num].size);
940 		}
941 
942 	      if (mem_base_reg_known && mem_offset_known && mem_mode_known
943 		  && (mem_scaled_known
944 		      || (opc->operand_info[op_num].form
945 			  != tic6x_operand_mem_ndw)))
946 		{
947 		  char side;
948 		  char base[4];
949 		  bfd_boolean offset_is_reg;
950 		  bfd_boolean offset_scaled;
951 		  char offset[4];
952 		  char offsetp[6];
953 
954 		  if (operands_text[op_num] || operands_pcrel[op_num])
955 		    abort ();
956 
957 		  side = func_unit_side == 2 ? 'b' : 'a';
958 		  snprintf (base, 4, "%c%u", side, mem_base_reg);
959 
960 		  offset_is_reg = ((mem_mode & 4) ? TRUE : FALSE);
961 		  if (offset_is_reg)
962 		    {
963 		      snprintf (offset, 4, "%c%u", side, mem_offset);
964 		      if (opc->operand_info[op_num].form
965 			  == tic6x_operand_mem_ndw)
966 			offset_scaled = mem_scaled ? TRUE : FALSE;
967 		      else
968 			offset_scaled = TRUE;
969 		    }
970 		  else
971 		    {
972 		      if (opc->operand_info[op_num].form
973 			  == tic6x_operand_mem_ndw)
974 			{
975 			  offset_scaled = mem_scaled ? TRUE : FALSE;
976 			  snprintf (offset, 4, "%u", mem_offset);
977 			}
978 		      else
979 			{
980 			  offset_scaled = FALSE;
981 			  snprintf (offset, 4, "%u",
982 				    (mem_offset
983 				     * opc->operand_info[op_num].size));
984 			}
985 		    }
986 
987 		  if (offset_scaled)
988 		    snprintf (offsetp, 6, "[%s]", offset);
989 		  else
990 		    snprintf (offsetp, 6, "(%s)", offset);
991 
992 		  operands_text[op_num] = TRUE;
993 		  switch (mem_mode & ~4u)
994 		    {
995 		    case 0:
996 		      snprintf (operands[op_num], 24, "*-%s%s", base, offsetp);
997 		      break;
998 
999 		    case 1:
1000 		      snprintf (operands[op_num], 24, "*+%s%s", base, offsetp);
1001 		      break;
1002 
1003 		    case 2:
1004 		    case 3:
1005 		      operands_ok = FALSE;
1006 		      break;
1007 
1008 		    case 8:
1009 		      snprintf (operands[op_num], 24, "*--%s%s", base,
1010 				offsetp);
1011 		      break;
1012 
1013 		    case 9:
1014 		      snprintf (operands[op_num], 24, "*++%s%s", base,
1015 				offsetp);
1016 		      break;
1017 
1018 		    case 10:
1019 		      snprintf (operands[op_num], 24, "*%s--%s", base,
1020 				offsetp);
1021 		      break;
1022 
1023 		    case 11:
1024 		      snprintf (operands[op_num], 24, "*%s++%s", base,
1025 				offsetp);
1026 		      break;
1027 
1028 		    default:
1029 		      abort ();
1030 		    }
1031 		}
1032 
1033 	      if (crlo_known && crhi_known)
1034 		{
1035 		  tic6x_rw rw;
1036 		  tic6x_ctrl_id crid;
1037 
1038 		  if (operands_text[op_num] || operands_pcrel[op_num])
1039 		    abort ();
1040 
1041 		  rw = opc->operand_info[op_num].rw;
1042 		  if (rw != tic6x_rw_read
1043 		      && rw != tic6x_rw_write)
1044 		    abort ();
1045 
1046 		  for (crid = 0; crid < tic6x_ctrl_max; crid++)
1047 		    {
1048 		      if (crlo == tic6x_ctrl_table[crid].crlo
1049 			  && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0
1050 			  && (rw == tic6x_rw_read
1051 			      ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read
1052 				 || (tic6x_ctrl_table[crid].rw
1053 				     == tic6x_rw_read_write))
1054 			      : (tic6x_ctrl_table[crid].rw == tic6x_rw_write
1055 				 || (tic6x_ctrl_table[crid].rw
1056 				     == tic6x_rw_read_write))))
1057 			break;
1058 		    }
1059 		  if (crid == tic6x_ctrl_max)
1060 		    {
1061 		      operands_text[op_num] = TRUE;
1062 		      operands_ok = FALSE;
1063 		    }
1064 		  else
1065 		    {
1066 		      operands_text[op_num] = TRUE;
1067 		      snprintf (operands[op_num], 24, "%s",
1068 				tic6x_ctrl_table[crid].name);
1069 		    }
1070 		}
1071 
1072 	      if (operands_text[op_num] || operands_pcrel[op_num]
1073 		  || spmask_skip_operand)
1074 		break;
1075 	    }
1076 	  if (spmask_skip_operand)
1077 	    {
1078 	      /* SPMASK operands are only valid as the single operand
1079 		 in the opcode table.  */
1080 	      if (num_operands != 1)
1081 		abort ();
1082 	      num_operands = 0;
1083 	      break;
1084 	    }
1085 	  /* The operand must by now have been decoded.  */
1086 	  if (!operands_text[op_num] && !operands_pcrel[op_num])
1087 	    abort ();
1088 	}
1089 
1090       if (!operands_ok)
1091 	continue;
1092 
1093       info->bytes_per_chunk = num_bits / 8;
1094       info->fprintf_func (info->stream, "%s%s%s%s", parallel, cond,
1095 			  opc->name, func_unit);
1096       for (op_num = 0; op_num < num_operands; op_num++)
1097 	{
1098 	  info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ','));
1099 	  if (operands_pcrel[op_num])
1100 	    info->print_address_func (operands_addresses[op_num], info);
1101 	  else
1102 	    info->fprintf_func (info->stream, "%s", operands[op_num]);
1103 	}
1104       if (fetch_packet_header_based && header.prot)
1105 	info->fprintf_func (info->stream, " || nop 5");
1106 
1107       return num_bits / 8;
1108     }
1109 
1110   info->bytes_per_chunk = num_bits / 8;
1111   info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>",
1112 		      (int) num_bits / 4, opcode);
1113   return num_bits / 8;
1114 }
1115