1c5dff60aSchristos /* TI C6X disassembler.
2*1424dfb3Schristos    Copyright (C) 2010-2020 Free Software Foundation, Inc.
3c5dff60aSchristos    Contributed by Joseph Myers <joseph@codesourcery.com>
4c5dff60aSchristos    		  Bernd Schmidt  <bernds@codesourcery.com>
5c5dff60aSchristos 
6c5dff60aSchristos    This file is part of libopcodes.
7c5dff60aSchristos 
8c5dff60aSchristos    This library is free software; you can redistribute it and/or modify
9c5dff60aSchristos    it under the terms of the GNU General Public License as published by
10c5dff60aSchristos    the Free Software Foundation; either version 3 of the License, or
11c5dff60aSchristos    (at your option) any later version.
12c5dff60aSchristos 
13c5dff60aSchristos    It is distributed in the hope that it will be useful, but WITHOUT
14c5dff60aSchristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15c5dff60aSchristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16c5dff60aSchristos    License for more details.
17c5dff60aSchristos 
18c5dff60aSchristos    You should have received a copy of the GNU General Public License
19c5dff60aSchristos    along with this program; if not, write to the Free Software
20c5dff60aSchristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21c5dff60aSchristos    MA 02110-1301, USA.  */
22c5dff60aSchristos 
23c5dff60aSchristos #include "sysdep.h"
2407163879Schristos #include "disassemble.h"
25c5dff60aSchristos #include "opcode/tic6x.h"
26c5dff60aSchristos #include "libiberty.h"
27c5dff60aSchristos 
28c5dff60aSchristos /* Define the instruction format table.  */
29c5dff60aSchristos const tic6x_insn_format tic6x_insn_format_table[tic6x_insn_format_max] =
30c5dff60aSchristos   {
31c5dff60aSchristos #define FMT(name, num_bits, cst_bits, mask, fields) \
32c5dff60aSchristos     { num_bits, cst_bits, mask, fields },
33c5dff60aSchristos #include "opcode/tic6x-insn-formats.h"
34c5dff60aSchristos #undef FMT
35c5dff60aSchristos   };
36c5dff60aSchristos 
37c5dff60aSchristos /* Define the control register table.  */
38c5dff60aSchristos const tic6x_ctrl tic6x_ctrl_table[tic6x_ctrl_max] =
39c5dff60aSchristos   {
40c5dff60aSchristos #define CTRL(name, isa, rw, crlo, crhi_mask)	\
41c5dff60aSchristos     {						\
42c5dff60aSchristos       STRINGX(name),				\
43c5dff60aSchristos       CONCAT2(TIC6X_INSN_,isa),			\
44c5dff60aSchristos       CONCAT2(tic6x_rw_,rw),			\
45c5dff60aSchristos       crlo,					\
46c5dff60aSchristos       crhi_mask					\
47c5dff60aSchristos     },
48c5dff60aSchristos #include "opcode/tic6x-control-registers.h"
49c5dff60aSchristos #undef CTRL
50c5dff60aSchristos   };
51c5dff60aSchristos 
52c5dff60aSchristos /* Define the opcode table.  */
53c5dff60aSchristos const tic6x_opcode tic6x_opcode_table[tic6x_opcode_max] =
54c5dff60aSchristos   {
557af5a897Schristos #define INSNU(name, func_unit, format, type, isa, flags, fixed, ops, var) \
567af5a897Schristos     {									\
577af5a897Schristos       STRINGX(name),							\
587af5a897Schristos       CONCAT2(tic6x_func_unit_,func_unit),				\
597af5a897Schristos       CONCAT3(tic6x_insn_format,_,format),	      			\
607af5a897Schristos       CONCAT2(tic6x_pipeline_,type),					\
617af5a897Schristos       CONCAT2(TIC6X_INSN_,isa),						\
627af5a897Schristos       flags,								\
637af5a897Schristos       fixed,								\
647af5a897Schristos       ops,								\
657af5a897Schristos       var								\
667af5a897Schristos     },
677af5a897Schristos #define INSNUE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
687af5a897Schristos     {									\
697af5a897Schristos       STRINGX(name),							\
707af5a897Schristos       CONCAT2(tic6x_func_unit_,func_unit),				\
717af5a897Schristos       CONCAT3(tic6x_insn_format,_,format),	      			\
727af5a897Schristos       CONCAT2(tic6x_pipeline_,type),					\
737af5a897Schristos       CONCAT2(TIC6X_INSN_,isa),						\
747af5a897Schristos       flags,								\
757af5a897Schristos       fixed,								\
767af5a897Schristos       ops,								\
777af5a897Schristos       var								\
787af5a897Schristos     },
79c5dff60aSchristos #define INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \
80c5dff60aSchristos     {									\
81c5dff60aSchristos       STRINGX(name),							\
82c5dff60aSchristos       CONCAT2(tic6x_func_unit_,func_unit),				\
83c5dff60aSchristos       CONCAT4(tic6x_insn_format_,func_unit,_,format),			\
84c5dff60aSchristos       CONCAT2(tic6x_pipeline_,type),					\
85c5dff60aSchristos       CONCAT2(TIC6X_INSN_,isa),						\
86c5dff60aSchristos       flags,								\
87c5dff60aSchristos       fixed,								\
88c5dff60aSchristos       ops,								\
89c5dff60aSchristos       var								\
90c5dff60aSchristos     },
91c5dff60aSchristos #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
92c5dff60aSchristos     {									\
93c5dff60aSchristos       STRINGX(name),							\
94c5dff60aSchristos       CONCAT2(tic6x_func_unit_,func_unit),				\
95c5dff60aSchristos       CONCAT4(tic6x_insn_format_,func_unit,_,format),			\
96c5dff60aSchristos       CONCAT2(tic6x_pipeline_,type),					\
97c5dff60aSchristos       CONCAT2(TIC6X_INSN_,isa),						\
98c5dff60aSchristos       flags,								\
99c5dff60aSchristos       fixed,								\
100c5dff60aSchristos       ops,								\
101c5dff60aSchristos       var								\
102c5dff60aSchristos     },
103c5dff60aSchristos #include "opcode/tic6x-opcode-table.h"
104c5dff60aSchristos #undef INSN
105c5dff60aSchristos #undef INSNE
1067af5a897Schristos #undef INSNU
1077af5a897Schristos #undef INSNUE
108c5dff60aSchristos   };
109c5dff60aSchristos 
110c5dff60aSchristos /* If instruction format FMT has a field FIELD, return a pointer to
111c5dff60aSchristos    the description of that field; otherwise return NULL.  */
112c5dff60aSchristos 
113c5dff60aSchristos const tic6x_insn_field *
tic6x_field_from_fmt(const tic6x_insn_format * fmt,tic6x_insn_field_id field)114c5dff60aSchristos tic6x_field_from_fmt (const tic6x_insn_format *fmt, tic6x_insn_field_id field)
115c5dff60aSchristos {
116c5dff60aSchristos   unsigned int f;
117c5dff60aSchristos 
118c5dff60aSchristos   for (f = 0; f < fmt->num_fields; f++)
119c5dff60aSchristos     if (fmt->fields[f].field_id == field)
120c5dff60aSchristos       return &fmt->fields[f];
121c5dff60aSchristos 
122c5dff60aSchristos   return NULL;
123c5dff60aSchristos }
124c5dff60aSchristos 
1257af5a897Schristos /* Extract the field width.  */
1267af5a897Schristos 
1277af5a897Schristos static unsigned int
tic6x_field_width(const tic6x_insn_field * field)1287af5a897Schristos tic6x_field_width (const tic6x_insn_field *field)
1297af5a897Schristos {
1307af5a897Schristos   unsigned int i;
1317af5a897Schristos   unsigned int width = 0;
1327af5a897Schristos 
1337af5a897Schristos   if (!field->num_bitfields)
1347af5a897Schristos     return field->bitfields[0].width;
1357af5a897Schristos 
1367af5a897Schristos   for (i = 0 ; i < field->num_bitfields ; i++)
1377af5a897Schristos     width += field->bitfields[i].width;
1387af5a897Schristos 
1397af5a897Schristos   return width;
1407af5a897Schristos }
1417af5a897Schristos 
142c5dff60aSchristos /* Extract the bits corresponding to FIELD from OPCODE.  */
143c5dff60aSchristos 
144c5dff60aSchristos static unsigned int
tic6x_field_bits(unsigned int opcode,const tic6x_insn_field * field)145c5dff60aSchristos tic6x_field_bits (unsigned int opcode, const tic6x_insn_field *field)
146c5dff60aSchristos {
1477af5a897Schristos   unsigned int i;
1487af5a897Schristos   unsigned int val = 0;
1497af5a897Schristos 
1507af5a897Schristos   if (!field->num_bitfields)
1517af5a897Schristos     return (opcode >> field->bitfields[0].low_pos) & ((1u << field->bitfields[0].width) - 1);
1527af5a897Schristos 
1537af5a897Schristos   for (i = 0 ; i < field->num_bitfields ; i++)
1547af5a897Schristos     val |= ((opcode >> field->bitfields[i].low_pos) & ((1u << field->bitfields[i].width) - 1))
1557af5a897Schristos       << field->bitfields[i].pos;
1567af5a897Schristos 
1577af5a897Schristos   return val;
158c5dff60aSchristos }
159c5dff60aSchristos 
160c5dff60aSchristos /* Extract a 32-bit value read from the instruction stream.  */
161c5dff60aSchristos 
162c5dff60aSchristos static unsigned int
tic6x_extract_32(unsigned char * p,struct disassemble_info * info)163c5dff60aSchristos tic6x_extract_32 (unsigned char *p, struct disassemble_info *info)
164c5dff60aSchristos {
165c5dff60aSchristos   if (info->endian == BFD_ENDIAN_LITTLE)
166*1424dfb3Schristos     return p[0] | (p[1] << 8) | (p[2] << 16) | ((unsigned) p[3] << 24);
167c5dff60aSchristos   else
168*1424dfb3Schristos     return p[3] | (p[2] << 8) | (p[1] << 16) | ((unsigned) p[0] << 24);
169c5dff60aSchristos }
170c5dff60aSchristos 
171c5dff60aSchristos /* Extract a 16-bit value read from the instruction stream.  */
172c5dff60aSchristos 
173c5dff60aSchristos static unsigned int
tic6x_extract_16(unsigned char * p,tic6x_fetch_packet_header * header,struct disassemble_info * info)1747af5a897Schristos tic6x_extract_16 (unsigned char *p, tic6x_fetch_packet_header *header,
1757af5a897Schristos                   struct disassemble_info *info)
176c5dff60aSchristos {
1777af5a897Schristos   unsigned int op16;
1787af5a897Schristos 
179c5dff60aSchristos   if (info->endian == BFD_ENDIAN_LITTLE)
1807af5a897Schristos     op16 = (p[0]) | (p[1] << 8);
181c5dff60aSchristos   else
1827af5a897Schristos     op16 = (p[1]) | (p[0] << 8);
1837af5a897Schristos   op16 |= (header->sat << TIC6X_COMPACT_SAT_POS);
1847af5a897Schristos   op16 |= (header->br << TIC6X_COMPACT_BR_POS);
1857af5a897Schristos   op16 |= (header->dsz << TIC6X_COMPACT_DSZ_POS);
1867af5a897Schristos   return op16;
187c5dff60aSchristos }
188c5dff60aSchristos 
189c5dff60aSchristos /* FP points to a fetch packet.  Return whether it is header-based; if
190c5dff60aSchristos    it is, fill in HEADER.  */
191c5dff60aSchristos 
192c5dff60aSchristos static bfd_boolean
tic6x_check_fetch_packet_header(unsigned char * fp,tic6x_fetch_packet_header * header,struct disassemble_info * info)193c5dff60aSchristos tic6x_check_fetch_packet_header (unsigned char *fp,
194c5dff60aSchristos 				 tic6x_fetch_packet_header *header,
195c5dff60aSchristos 				 struct disassemble_info *info)
196c5dff60aSchristos {
197c5dff60aSchristos   int i;
198c5dff60aSchristos 
199c5dff60aSchristos   header->header = tic6x_extract_32 (fp + 28, info);
2007af5a897Schristos 
201c5dff60aSchristos   if ((header->header & 0xf0000000) != 0xe0000000)
2027af5a897Schristos     {
2037af5a897Schristos       header->prot = 0;
2047af5a897Schristos       header->rs = 0;
2057af5a897Schristos       header->dsz = 0;
2067af5a897Schristos       header->br = 0;
2077af5a897Schristos       header->sat = 0;
2087af5a897Schristos       for (i = 0; i < 7; i++)
2097af5a897Schristos 	header->word_compact[i] = FALSE;
2107af5a897Schristos       for (i = 0; i < 14; i++)
2117af5a897Schristos 	header->p_bits[i] = FALSE;
212c5dff60aSchristos       return FALSE;
2137af5a897Schristos     }
214c5dff60aSchristos 
215c5dff60aSchristos   for (i = 0; i < 7; i++)
216c5dff60aSchristos     header->word_compact[i]
217c5dff60aSchristos       = (header->header & (1u << (21 + i))) ? TRUE : FALSE;
218c5dff60aSchristos 
219c5dff60aSchristos   header->prot = (header->header & (1u << 20)) ? TRUE : FALSE;
220c5dff60aSchristos   header->rs = (header->header & (1u << 19)) ? TRUE : FALSE;
221c5dff60aSchristos   header->dsz = (header->header >> 16) & 0x7;
222c5dff60aSchristos   header->br = (header->header & (1u << 15)) ? TRUE : FALSE;
223c5dff60aSchristos   header->sat = (header->header & (1u << 14)) ? TRUE : FALSE;
224c5dff60aSchristos 
225c5dff60aSchristos   for (i = 0; i < 14; i++)
226c5dff60aSchristos     header->p_bits[i]
227c5dff60aSchristos       = (header->header & (1u << i)) ? TRUE : FALSE;
228c5dff60aSchristos 
229c5dff60aSchristos   return TRUE;
230c5dff60aSchristos }
231c5dff60aSchristos 
232c5dff60aSchristos /* Disassemble the instruction at ADDR and print it using
233c5dff60aSchristos    INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes
234c5dff60aSchristos    consumed.  */
235c5dff60aSchristos 
236c5dff60aSchristos int
print_insn_tic6x(bfd_vma addr,struct disassemble_info * info)237c5dff60aSchristos print_insn_tic6x (bfd_vma addr, struct disassemble_info *info)
238c5dff60aSchristos {
239c5dff60aSchristos   int status;
240c5dff60aSchristos   bfd_vma fp_addr;
241c5dff60aSchristos   bfd_vma fp_offset;
242c5dff60aSchristos   unsigned char fp[32];
243c5dff60aSchristos   unsigned int opcode;
244c5dff60aSchristos   tic6x_opcode_id opcode_id;
245c5dff60aSchristos   bfd_boolean fetch_packet_header_based;
246c5dff60aSchristos   tic6x_fetch_packet_header header;
247c5dff60aSchristos   unsigned int num_bits;
248c5dff60aSchristos   bfd_boolean bad_offset = FALSE;
249c5dff60aSchristos 
250c5dff60aSchristos   fp_offset = addr & 0x1f;
251c5dff60aSchristos   fp_addr = addr - fp_offset;
252ed6a76a9Schristos   /* Read in a block of instructions.  Since there might be a
253ed6a76a9Schristos      symbol in the middle of this block, disable stop_vma.  */
254ed6a76a9Schristos   info->stop_vma = 0;
255c5dff60aSchristos   status = info->read_memory_func (fp_addr, fp, 32, info);
256c5dff60aSchristos   if (status)
257c5dff60aSchristos     {
258c5dff60aSchristos       info->memory_error_func (status, addr, info);
259c5dff60aSchristos       return -1;
260c5dff60aSchristos     }
261c5dff60aSchristos 
262c5dff60aSchristos   fetch_packet_header_based
263c5dff60aSchristos     = tic6x_check_fetch_packet_header (fp, &header, info);
264c5dff60aSchristos   if (fetch_packet_header_based)
265c5dff60aSchristos     {
266c5dff60aSchristos       if (fp_offset & 0x1)
267c5dff60aSchristos 	bad_offset = TRUE;
268c5dff60aSchristos       if ((fp_offset & 0x3) && (fp_offset >= 28
269c5dff60aSchristos 				|| !header.word_compact[fp_offset >> 2]))
270c5dff60aSchristos 	bad_offset = TRUE;
271c5dff60aSchristos       if (fp_offset == 28)
272c5dff60aSchristos 	{
273c5dff60aSchristos 	  info->bytes_per_chunk = 4;
274c5dff60aSchristos 	  info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>",
275c5dff60aSchristos 			      header.header);
276c5dff60aSchristos 	  return 4;
277c5dff60aSchristos 	}
278c5dff60aSchristos       num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32);
279c5dff60aSchristos     }
280c5dff60aSchristos   else
281c5dff60aSchristos     {
282c5dff60aSchristos       num_bits = 32;
283c5dff60aSchristos       if (fp_offset & 0x3)
284c5dff60aSchristos 	bad_offset = TRUE;
285c5dff60aSchristos     }
286c5dff60aSchristos 
287c5dff60aSchristos   if (bad_offset)
288c5dff60aSchristos     {
289c5dff60aSchristos       info->bytes_per_chunk = 1;
290c5dff60aSchristos       info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]);
291c5dff60aSchristos       return 1;
292c5dff60aSchristos     }
293c5dff60aSchristos 
294c5dff60aSchristos   if (num_bits == 16)
295c5dff60aSchristos     {
296c5dff60aSchristos       /* The least-significant part of a 32-bit word comes logically
297c5dff60aSchristos 	 before the most-significant part.  For big-endian, follow the
298c5dff60aSchristos 	 TI assembler in showing instructions in logical order by
299c5dff60aSchristos 	 pretending that the two halves of the word are in opposite
300c5dff60aSchristos 	 locations to where they actually are.  */
301c5dff60aSchristos       if (info->endian == BFD_ENDIAN_LITTLE)
3027af5a897Schristos 	opcode = tic6x_extract_16 (fp + fp_offset, &header, info);
303c5dff60aSchristos       else
3047af5a897Schristos 	opcode = tic6x_extract_16 (fp + (fp_offset ^ 2), &header, info);
305c5dff60aSchristos     }
306c5dff60aSchristos   else
307c5dff60aSchristos     opcode = tic6x_extract_32 (fp + fp_offset, info);
308c5dff60aSchristos 
309c5dff60aSchristos   for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++)
310c5dff60aSchristos     {
311c5dff60aSchristos       const tic6x_opcode *const opc = &tic6x_opcode_table[opcode_id];
312c5dff60aSchristos       const tic6x_insn_format *const fmt
313c5dff60aSchristos 	= &tic6x_insn_format_table[opc->format];
314c5dff60aSchristos       const tic6x_insn_field *creg_field;
315c5dff60aSchristos       bfd_boolean p_bit;
316c5dff60aSchristos       const char *parallel;
317c5dff60aSchristos       const char *cond = "";
318c5dff60aSchristos       const char *func_unit;
3191c468f90Schristos       char func_unit_buf[8];
320c5dff60aSchristos       unsigned int func_unit_side = 0;
321c5dff60aSchristos       unsigned int func_unit_data_side = 0;
322c5dff60aSchristos       unsigned int func_unit_cross = 0;
3237af5a897Schristos       unsigned int t_val = 0;
324c5dff60aSchristos       /* The maximum length of the text of a non-PC-relative operand
325c5dff60aSchristos 	 is 24 bytes (SPMASK masking all eight functional units, with
326c5dff60aSchristos 	 separating commas and trailing NUL).  */
327c5dff60aSchristos       char operands[TIC6X_MAX_OPERANDS][24] = { { 0 } };
328c5dff60aSchristos       bfd_vma operands_addresses[TIC6X_MAX_OPERANDS] = { 0 };
329c5dff60aSchristos       bfd_boolean operands_text[TIC6X_MAX_OPERANDS] = { FALSE };
330c5dff60aSchristos       bfd_boolean operands_pcrel[TIC6X_MAX_OPERANDS] = { FALSE };
331c5dff60aSchristos       unsigned int fix;
332c5dff60aSchristos       unsigned int num_operands;
333c5dff60aSchristos       unsigned int op_num;
334c5dff60aSchristos       bfd_boolean fixed_ok;
335c5dff60aSchristos       bfd_boolean operands_ok;
3367af5a897Schristos       bfd_boolean have_t = FALSE;
337c5dff60aSchristos 
338c5dff60aSchristos       if (opc->flags & TIC6X_FLAG_MACRO)
339c5dff60aSchristos 	continue;
340c5dff60aSchristos       if (fmt->num_bits != num_bits)
341c5dff60aSchristos 	continue;
342c5dff60aSchristos       if ((opcode & fmt->mask) != fmt->cst_bits)
343c5dff60aSchristos 	continue;
344c5dff60aSchristos 
345c5dff60aSchristos       /* If the format has a creg field, it is only a candidate for a
346c5dff60aSchristos 	 match if the creg and z fields have values indicating a valid
347c5dff60aSchristos 	 condition; reserved values indicate either an instruction
348c5dff60aSchristos 	 format without a creg field, or an invalid instruction.  */
349c5dff60aSchristos       creg_field = tic6x_field_from_fmt (fmt, tic6x_field_creg);
350c5dff60aSchristos       if (creg_field)
351c5dff60aSchristos 	{
352c5dff60aSchristos 	  const tic6x_insn_field *z_field;
353c5dff60aSchristos 	  unsigned int creg_value, z_value;
354c5dff60aSchristos 	  static const char *const conds[8][2] =
355c5dff60aSchristos 	    {
356c5dff60aSchristos 	      { "", NULL },
357c5dff60aSchristos 	      { "[b0] ", "[!b0] " },
358c5dff60aSchristos 	      { "[b1] ", "[!b1] " },
359c5dff60aSchristos 	      { "[b2] ", "[!b2] " },
360c5dff60aSchristos 	      { "[a1] ", "[!a1] " },
361c5dff60aSchristos 	      { "[a2] ", "[!a2] " },
362c5dff60aSchristos 	      { "[a0] ", "[!a0] " },
363c5dff60aSchristos 	      { NULL, NULL }
364c5dff60aSchristos 	    };
365c5dff60aSchristos 
366c5dff60aSchristos 	  /* A creg field is not meaningful without a z field, so if
367c5dff60aSchristos 	     the z field is not present this is an error in the format
368c5dff60aSchristos 	     table.  */
369c5dff60aSchristos 	  z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
370c5dff60aSchristos 	  if (!z_field)
3717af5a897Schristos 	    {
3727af5a897Schristos 	      printf ("*** opcode %x: missing z field", opcode);
373c5dff60aSchristos 	      abort ();
3747af5a897Schristos 	    }
375c5dff60aSchristos 
376c5dff60aSchristos 	  creg_value = tic6x_field_bits (opcode, creg_field);
377c5dff60aSchristos 	  z_value = tic6x_field_bits (opcode, z_field);
378c5dff60aSchristos 	  cond = conds[creg_value][z_value];
379c5dff60aSchristos 	  if (cond == NULL)
380c5dff60aSchristos 	    continue;
381c5dff60aSchristos 	}
382c5dff60aSchristos 
3837af5a897Schristos       if (opc->flags & TIC6X_FLAG_INSN16_SPRED)
3847af5a897Schristos 	{
3857af5a897Schristos 	  const tic6x_insn_field *cc_field;
3867af5a897Schristos           unsigned int s_value = 0;
3877af5a897Schristos           unsigned int z_value = 0;
3887af5a897Schristos           bfd_boolean cond_known = FALSE;
3897af5a897Schristos           static const char *const conds[2][2] =
3907af5a897Schristos             {
3917af5a897Schristos               { "[a0] ", "[!a0] " },
3927af5a897Schristos               { "[b0] ", "[!b0] " }
3937af5a897Schristos             };
3947af5a897Schristos 
3957af5a897Schristos           cc_field = tic6x_field_from_fmt (fmt, tic6x_field_cc);
3967af5a897Schristos 
3977af5a897Schristos           if (cc_field)
3987af5a897Schristos 	    {
3997af5a897Schristos 	      unsigned int cc_value;
4007af5a897Schristos 
4017af5a897Schristos 	      cc_value = tic6x_field_bits (opcode, cc_field);
4027af5a897Schristos 	      s_value = (cc_value & 0x2) >> 1;
4037af5a897Schristos 	      z_value = (cc_value & 0x1);
4047af5a897Schristos 	      cond_known = TRUE;
4057af5a897Schristos 	    }
4067af5a897Schristos 	  else
4077af5a897Schristos 	    {
4087af5a897Schristos 	      const tic6x_insn_field *z_field;
4097af5a897Schristos 	      const tic6x_insn_field *s_field;
4107af5a897Schristos 
4117af5a897Schristos 	      s_field = tic6x_field_from_fmt (fmt, tic6x_field_s);
4127af5a897Schristos 
4137af5a897Schristos 	      if (!s_field)
4147af5a897Schristos 		{
4157af5a897Schristos 		  printf ("opcode %x: missing compact insn predicate register field (s field)\n",
4167af5a897Schristos 			  opcode);
4177af5a897Schristos 		  abort ();
4187af5a897Schristos 		}
4197af5a897Schristos 	      s_value = tic6x_field_bits (opcode, s_field);
4207af5a897Schristos 	      z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
4217af5a897Schristos 	      if (!z_field)
4227af5a897Schristos 		{
4237af5a897Schristos 		  printf ("opcode %x: missing compact insn predicate z_value (z field)\n", opcode);
4247af5a897Schristos 		  abort ();
4257af5a897Schristos 		}
4267af5a897Schristos 
4277af5a897Schristos 	      z_value = tic6x_field_bits (opcode, z_field);
4287af5a897Schristos 	      cond_known = TRUE;
4297af5a897Schristos 	    }
4307af5a897Schristos 
4317af5a897Schristos           if (!cond_known)
4327af5a897Schristos 	    {
4337af5a897Schristos 	      printf ("opcode %x: unspecified ompact insn predicate\n", opcode);
4347af5a897Schristos 	      abort ();
4357af5a897Schristos 	    }
4367af5a897Schristos           cond = conds[s_value][z_value];
4377af5a897Schristos 	}
4387af5a897Schristos 
439c5dff60aSchristos       /* All fixed fields must have matching values; all fields with
440c5dff60aSchristos 	 restricted ranges must have values within those ranges.  */
441c5dff60aSchristos       fixed_ok = TRUE;
442c5dff60aSchristos       for (fix = 0; fix < opc->num_fixed_fields; fix++)
443c5dff60aSchristos 	{
444c5dff60aSchristos 	  unsigned int field_bits;
445c5dff60aSchristos 	  const tic6x_insn_field *const field
446c5dff60aSchristos 	    = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id);
447c5dff60aSchristos 
448c5dff60aSchristos 	  if (!field)
4497af5a897Schristos 	    {
4507af5a897Schristos 	      printf ("opcode %x: missing field #%d for FIX #%d\n",
4517af5a897Schristos 		      opcode, opc->fixed_fields[fix].field_id, fix);
452c5dff60aSchristos 	      abort ();
4537af5a897Schristos 	    }
4547af5a897Schristos 
455c5dff60aSchristos 	  field_bits = tic6x_field_bits (opcode, field);
456c5dff60aSchristos 	  if (field_bits < opc->fixed_fields[fix].min_val
457c5dff60aSchristos 	      || field_bits > opc->fixed_fields[fix].max_val)
458c5dff60aSchristos 	    {
459c5dff60aSchristos 	      fixed_ok = FALSE;
460c5dff60aSchristos 	      break;
461c5dff60aSchristos 	    }
462c5dff60aSchristos 	}
463c5dff60aSchristos       if (!fixed_ok)
464c5dff60aSchristos 	continue;
465c5dff60aSchristos 
466c5dff60aSchristos       /* The instruction matches.  */
467c5dff60aSchristos 
468c5dff60aSchristos       /* The p-bit indicates whether this instruction is in parallel
469c5dff60aSchristos 	 with the *next* instruction, whereas the parallel bars
470c5dff60aSchristos 	 indicate the instruction is in parallel with the *previous*
471c5dff60aSchristos 	 instruction.  Thus, we must find the p-bit for the previous
472c5dff60aSchristos 	 instruction.  */
473c5dff60aSchristos       if (num_bits == 16 && (fp_offset & 0x2) == 2)
474c5dff60aSchristos 	{
475c5dff60aSchristos 	  /* This is the logically second (most significant; second in
476c5dff60aSchristos 	     fp_offset terms because fp_offset relates to logical not
477c5dff60aSchristos 	     physical addresses) instruction of a compact pair; find
478c5dff60aSchristos 	     the p-bit for the first (least significant).  */
479c5dff60aSchristos 	  p_bit = header.p_bits[(fp_offset >> 2) << 1];
480c5dff60aSchristos 	}
481c5dff60aSchristos       else if (fp_offset >= 4)
482c5dff60aSchristos 	{
483c5dff60aSchristos 	  /* Find the last instruction of the previous word in this
484c5dff60aSchristos 	     fetch packet.  For compact instructions, this is the most
485c5dff60aSchristos 	     significant 16 bits.  */
486c5dff60aSchristos 	  if (fetch_packet_header_based
487c5dff60aSchristos 	      && header.word_compact[(fp_offset >> 2) - 1])
488c5dff60aSchristos 	    p_bit = header.p_bits[(fp_offset >> 1) - 1];
489c5dff60aSchristos 	  else
490c5dff60aSchristos 	    {
491c5dff60aSchristos 	      unsigned int prev_opcode
492c5dff60aSchristos 		= tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info);
493c5dff60aSchristos 	      p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
494c5dff60aSchristos 	    }
495c5dff60aSchristos 	}
496c5dff60aSchristos       else
497c5dff60aSchristos 	{
498c5dff60aSchristos 	  /* Find the last instruction of the previous fetch
499c5dff60aSchristos 	     packet.  */
500c5dff60aSchristos 	  unsigned char fp_prev[32];
5017af5a897Schristos 
502c5dff60aSchristos 	  status = info->read_memory_func (fp_addr - 32, fp_prev, 32, info);
503c5dff60aSchristos 	  if (status)
504c5dff60aSchristos 	    /* No previous instruction to be parallel with.  */
505c5dff60aSchristos 	    p_bit = FALSE;
506c5dff60aSchristos 	  else
507c5dff60aSchristos 	    {
508c5dff60aSchristos 	      bfd_boolean prev_header_based;
509c5dff60aSchristos 	      tic6x_fetch_packet_header prev_header;
510c5dff60aSchristos 
511c5dff60aSchristos 	      prev_header_based
512c5dff60aSchristos 		= tic6x_check_fetch_packet_header (fp_prev, &prev_header, info);
5131c468f90Schristos 	      if (prev_header_based)
5141c468f90Schristos 		{
5151c468f90Schristos 		  if (prev_header.word_compact[6])
516c5dff60aSchristos 		    p_bit = prev_header.p_bits[13];
517c5dff60aSchristos 		  else
518c5dff60aSchristos 		    {
5191c468f90Schristos 		      unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 24,
5201c468f90Schristos 								   info);
5211c468f90Schristos 		      p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
5221c468f90Schristos 		    }
5231c468f90Schristos 		}
5241c468f90Schristos 	      else
5251c468f90Schristos 		{
526c5dff60aSchristos 		  unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28,
527c5dff60aSchristos 							       info);
528c5dff60aSchristos 		  p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
529c5dff60aSchristos 		}
530c5dff60aSchristos 	    }
531c5dff60aSchristos 	}
532c5dff60aSchristos       parallel = p_bit ? "|| " : "";
533c5dff60aSchristos 
534c5dff60aSchristos       if (opc->func_unit == tic6x_func_unit_nfu)
535c5dff60aSchristos 	func_unit = "";
536c5dff60aSchristos       else
537c5dff60aSchristos 	{
538c5dff60aSchristos 	  unsigned int fld_num;
539c5dff60aSchristos 	  char func_unit_char;
540c5dff60aSchristos 	  const char *data_str;
541c5dff60aSchristos 	  bfd_boolean have_areg = FALSE;
542c5dff60aSchristos 	  bfd_boolean have_cross = FALSE;
543c5dff60aSchristos 
544c5dff60aSchristos 	  func_unit_side = (opc->flags & TIC6X_FLAG_SIDE_B_ONLY) ? 2 : 0;
545c5dff60aSchristos 	  func_unit_cross = 0;
546c5dff60aSchristos 	  func_unit_data_side = (opc->flags & TIC6X_FLAG_SIDE_T2_ONLY) ? 2 : 0;
547c5dff60aSchristos 
548c5dff60aSchristos 	  for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
549c5dff60aSchristos 	    {
550c5dff60aSchristos 	      const tic6x_coding_field *const enc = &opc->variable_fields[fld_num];
551c5dff60aSchristos 	      const tic6x_insn_field *field;
552c5dff60aSchristos 	      unsigned int fld_val;
553c5dff60aSchristos 
554c5dff60aSchristos 	      field = tic6x_field_from_fmt (fmt, enc->field_id);
5557af5a897Schristos 
556c5dff60aSchristos 	      if (!field)
5577af5a897Schristos 		{
5587af5a897Schristos 		  printf ("opcode %x: could not retrieve field (field_id:%d)\n",
5597af5a897Schristos 			  opcode, fld_num);
560c5dff60aSchristos 		  abort ();
5617af5a897Schristos 		}
5627af5a897Schristos 
563c5dff60aSchristos 	      fld_val = tic6x_field_bits (opcode, field);
5647af5a897Schristos 
565c5dff60aSchristos 	      switch (enc->coding_method)
566c5dff60aSchristos 		{
567c5dff60aSchristos 		case tic6x_coding_fu:
568c5dff60aSchristos 		  /* The side must be specified exactly once.  */
569c5dff60aSchristos 		  if (func_unit_side)
5707af5a897Schristos 		    {
5717af5a897Schristos 		      printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
5727af5a897Schristos 			      opcode, fld_num);
573c5dff60aSchristos 		      abort ();
5747af5a897Schristos 		    }
575c5dff60aSchristos 		  func_unit_side = (fld_val ? 2 : 1);
576c5dff60aSchristos 		  break;
577c5dff60aSchristos 
578c5dff60aSchristos 		case tic6x_coding_data_fu:
579c5dff60aSchristos 		  /* The data side must be specified exactly once.  */
580c5dff60aSchristos 		  if (func_unit_data_side)
5817af5a897Schristos 		    {
5827af5a897Schristos 		      printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
5837af5a897Schristos 			      opcode, fld_num);
584c5dff60aSchristos 		      abort ();
5857af5a897Schristos 		    }
586c5dff60aSchristos 		  func_unit_data_side = (fld_val ? 2 : 1);
587c5dff60aSchristos 		  break;
588c5dff60aSchristos 
589c5dff60aSchristos 		case tic6x_coding_xpath:
590c5dff60aSchristos 		  /* Cross path use must be specified exactly
591c5dff60aSchristos 		     once.  */
592c5dff60aSchristos 		  if (have_cross)
5937af5a897Schristos 		    {
5947af5a897Schristos 		      printf ("opcode %x: field #%d use tic6x_coding_xpath, have_cross is already set!\n",
5957af5a897Schristos 			      opcode, fld_num);
596c5dff60aSchristos 		      abort ();
5977af5a897Schristos 		    }
598c5dff60aSchristos 		  have_cross = TRUE;
599c5dff60aSchristos 		  func_unit_cross = fld_val;
600c5dff60aSchristos 		  break;
601c5dff60aSchristos 
6027af5a897Schristos                 case tic6x_coding_rside:
6037af5a897Schristos                   /* If the format has a t field, use it for src/dst register side.  */
6047af5a897Schristos                   have_t = TRUE;
6057af5a897Schristos                   t_val = fld_val;
6067af5a897Schristos                   func_unit_data_side = (t_val ? 2 : 1);
6077af5a897Schristos                   break;
6087af5a897Schristos 
609c5dff60aSchristos 		case tic6x_coding_areg:
610c5dff60aSchristos 		  have_areg = TRUE;
611c5dff60aSchristos 		  break;
612c5dff60aSchristos 
613c5dff60aSchristos 		default:
614c5dff60aSchristos 		  /* Don't relate to functional units.  */
615c5dff60aSchristos 		  break;
616c5dff60aSchristos 		}
617c5dff60aSchristos 	    }
618c5dff60aSchristos 
619c5dff60aSchristos 	  /* The side of the functional unit used must now have been
620c5dff60aSchristos 	     determined either from the flags or from an instruction
621c5dff60aSchristos 	     field.  */
622c5dff60aSchristos 	  if (func_unit_side != 1 && func_unit_side != 2)
6237af5a897Schristos 	    {
6247af5a897Schristos 	      printf ("opcode %x: func_unit_side is not encoded!\n", opcode);
625c5dff60aSchristos 	      abort ();
6267af5a897Schristos 	    }
627c5dff60aSchristos 
628c5dff60aSchristos 	  /* Cross paths are not applicable when sides are specified
629c5dff60aSchristos 	     for both address and data paths.  */
630c5dff60aSchristos 	  if (func_unit_data_side && have_cross)
6317af5a897Schristos 	    {
6327af5a897Schristos 	      printf ("opcode %x: xpath not applicable when side are specified both for address and data!\n",
6337af5a897Schristos 		      opcode);
634c5dff60aSchristos 	      abort ();
6357af5a897Schristos 	    }
636c5dff60aSchristos 
637c5dff60aSchristos 	  /* Separate address and data paths are only applicable for
638c5dff60aSchristos 	     the D unit.  */
639c5dff60aSchristos 	  if (func_unit_data_side && opc->func_unit != tic6x_func_unit_d)
6407af5a897Schristos 	    {
6417af5a897Schristos 	      printf ("opcode %x: separate address and data paths only applicable for D unit!\n",
6427af5a897Schristos 		      opcode);
643c5dff60aSchristos 	      abort ();
6447af5a897Schristos           }
645c5dff60aSchristos 
646c5dff60aSchristos 	  /* If an address register is being used but in ADDA rather
647c5dff60aSchristos 	     than a load or store, it uses a cross path for side-A
648c5dff60aSchristos 	     instructions, and the cross path use is not specified by
649c5dff60aSchristos 	     an instruction field.  */
650c5dff60aSchristos 	  if (have_areg && !func_unit_data_side)
651c5dff60aSchristos 	    {
652c5dff60aSchristos 	      if (have_cross)
6537af5a897Schristos 		{
6547af5a897Schristos 		  printf ("opcode %x: illegal cross path specifier in adda opcode!\n", opcode);
655c5dff60aSchristos 		  abort ();
6567af5a897Schristos 		}
657c5dff60aSchristos 	      func_unit_cross = (func_unit_side == 1 ? TRUE : FALSE);
658c5dff60aSchristos 	    }
659c5dff60aSchristos 
660c5dff60aSchristos 	  switch (opc->func_unit)
661c5dff60aSchristos 	    {
662c5dff60aSchristos 	    case tic6x_func_unit_d:
663c5dff60aSchristos 	      func_unit_char = 'D';
664c5dff60aSchristos 	      break;
665c5dff60aSchristos 
666c5dff60aSchristos 	    case tic6x_func_unit_l:
667c5dff60aSchristos 	      func_unit_char = 'L';
668c5dff60aSchristos 	      break;
669c5dff60aSchristos 
670c5dff60aSchristos 	    case tic6x_func_unit_m:
671c5dff60aSchristos 	      func_unit_char = 'M';
672c5dff60aSchristos 	      break;
673c5dff60aSchristos 
674c5dff60aSchristos 	    case tic6x_func_unit_s:
675c5dff60aSchristos 	      func_unit_char = 'S';
676c5dff60aSchristos 	      break;
677c5dff60aSchristos 
678c5dff60aSchristos 	    default:
6797af5a897Schristos               printf ("opcode %x: illegal func_unit specifier %d\n", opcode, opc->func_unit);
680c5dff60aSchristos 	      abort ();
681c5dff60aSchristos 	    }
682c5dff60aSchristos 
683c5dff60aSchristos 	  switch (func_unit_data_side)
684c5dff60aSchristos 	    {
685c5dff60aSchristos 	    case 0:
686c5dff60aSchristos 	      data_str = "";
687c5dff60aSchristos 	      break;
688c5dff60aSchristos 
689c5dff60aSchristos 	    case 1:
690c5dff60aSchristos 	      data_str = "T1";
691c5dff60aSchristos 	      break;
692c5dff60aSchristos 
693c5dff60aSchristos 	    case 2:
694c5dff60aSchristos 	      data_str = "T2";
695c5dff60aSchristos 	      break;
696c5dff60aSchristos 
697c5dff60aSchristos 	    default:
6987af5a897Schristos               printf ("opcode %x: illegal data func_unit specifier %d\n",
6997af5a897Schristos 		      opcode, func_unit_data_side);
700c5dff60aSchristos 	      abort ();
701c5dff60aSchristos 	    }
702c5dff60aSchristos 
7037af5a897Schristos 	  if (opc->flags & TIC6X_FLAG_INSN16_BSIDE && func_unit_side == 1)
7047af5a897Schristos 	      func_unit_cross = 1;
7057af5a897Schristos 
7061c468f90Schristos 	  snprintf (func_unit_buf, sizeof func_unit_buf, " .%c%u%s%s",
7071c468f90Schristos 		    func_unit_char, func_unit_side,
7081c468f90Schristos 		    (func_unit_cross ? "X" : ""), data_str);
709c5dff60aSchristos 	  func_unit = func_unit_buf;
710c5dff60aSchristos 	}
711c5dff60aSchristos 
712c5dff60aSchristos       /* For each operand there must be one or more fields set based
713c5dff60aSchristos 	 on that operand, that can together be used to derive the
714c5dff60aSchristos 	 operand value.  */
715c5dff60aSchristos       operands_ok = TRUE;
716c5dff60aSchristos       num_operands = opc->num_operands;
717c5dff60aSchristos       for (op_num = 0; op_num < num_operands; op_num++)
718c5dff60aSchristos 	{
719c5dff60aSchristos 	  unsigned int fld_num;
720c5dff60aSchristos 	  unsigned int mem_base_reg = 0;
721c5dff60aSchristos 	  bfd_boolean mem_base_reg_known = FALSE;
722c5dff60aSchristos 	  bfd_boolean mem_base_reg_known_long = FALSE;
723c5dff60aSchristos 	  unsigned int mem_offset = 0;
724c5dff60aSchristos 	  bfd_boolean mem_offset_known = FALSE;
725c5dff60aSchristos 	  bfd_boolean mem_offset_known_long = FALSE;
726c5dff60aSchristos 	  unsigned int mem_mode = 0;
727c5dff60aSchristos 	  bfd_boolean mem_mode_known = FALSE;
728c5dff60aSchristos 	  unsigned int mem_scaled = 0;
729c5dff60aSchristos 	  bfd_boolean mem_scaled_known = FALSE;
730c5dff60aSchristos 	  unsigned int crlo = 0;
731c5dff60aSchristos 	  bfd_boolean crlo_known = FALSE;
732c5dff60aSchristos 	  unsigned int crhi = 0;
733c5dff60aSchristos 	  bfd_boolean crhi_known = FALSE;
734c5dff60aSchristos 	  bfd_boolean spmask_skip_operand = FALSE;
735c5dff60aSchristos 	  unsigned int fcyc_bits = 0;
736c5dff60aSchristos 	  bfd_boolean prev_sploop_found = FALSE;
737c5dff60aSchristos 
738c5dff60aSchristos 	  switch (opc->operand_info[op_num].form)
739c5dff60aSchristos 	    {
7407af5a897Schristos 	    case tic6x_operand_b15reg:
7417af5a897Schristos 	      /* Fully determined by the functional unit.  */
7427af5a897Schristos 	      operands_text[op_num] = TRUE;
7437af5a897Schristos 	      snprintf (operands[op_num], 24, "b15");
7447af5a897Schristos 	      continue;
7457af5a897Schristos 
7467af5a897Schristos 	    case tic6x_operand_zreg:
7477af5a897Schristos 	      /* Fully determined by the functional unit.  */
7487af5a897Schristos 	      operands_text[op_num] = TRUE;
7497af5a897Schristos 	      snprintf (operands[op_num], 24, "%c0",
7507af5a897Schristos 			(func_unit_side == 2 ? 'b' : 'a'));
7517af5a897Schristos 	      continue;
7527af5a897Schristos 
753c5dff60aSchristos 	    case tic6x_operand_retreg:
754c5dff60aSchristos 	      /* Fully determined by the functional unit.  */
755c5dff60aSchristos 	      operands_text[op_num] = TRUE;
756c5dff60aSchristos 	      snprintf (operands[op_num], 24, "%c3",
757c5dff60aSchristos 			(func_unit_side == 2 ? 'b' : 'a'));
758c5dff60aSchristos 	      continue;
759c5dff60aSchristos 
760c5dff60aSchristos 	    case tic6x_operand_irp:
761c5dff60aSchristos 	      operands_text[op_num] = TRUE;
762c5dff60aSchristos 	      snprintf (operands[op_num], 24, "irp");
763c5dff60aSchristos 	      continue;
764c5dff60aSchristos 
765c5dff60aSchristos 	    case tic6x_operand_nrp:
766c5dff60aSchristos 	      operands_text[op_num] = TRUE;
767c5dff60aSchristos 	      snprintf (operands[op_num], 24, "nrp");
768c5dff60aSchristos 	      continue;
769c5dff60aSchristos 
7707af5a897Schristos 	    case tic6x_operand_ilc:
7717af5a897Schristos 	      operands_text[op_num] = TRUE;
7727af5a897Schristos 	      snprintf (operands[op_num], 24, "ilc");
7737af5a897Schristos 	      continue;
7747af5a897Schristos 
7757af5a897Schristos 	    case tic6x_operand_hw_const_minus_1:
7767af5a897Schristos 	      operands_text[op_num] = TRUE;
7777af5a897Schristos 	      snprintf (operands[op_num], 24, "-1");
7787af5a897Schristos 	      continue;
7797af5a897Schristos 
7807af5a897Schristos 	    case tic6x_operand_hw_const_0:
7817af5a897Schristos 	      operands_text[op_num] = TRUE;
7827af5a897Schristos 	      snprintf (operands[op_num], 24, "0");
7837af5a897Schristos 	      continue;
7847af5a897Schristos 
7857af5a897Schristos 	    case tic6x_operand_hw_const_1:
7867af5a897Schristos 	      operands_text[op_num] = TRUE;
7877af5a897Schristos 	      snprintf (operands[op_num], 24, "1");
7887af5a897Schristos 	      continue;
7897af5a897Schristos 
7907af5a897Schristos 	    case tic6x_operand_hw_const_5:
7917af5a897Schristos 	      operands_text[op_num] = TRUE;
7927af5a897Schristos 	      snprintf (operands[op_num], 24, "5");
7937af5a897Schristos 	      continue;
7947af5a897Schristos 
7957af5a897Schristos 	    case tic6x_operand_hw_const_16:
7967af5a897Schristos 	      operands_text[op_num] = TRUE;
7977af5a897Schristos 	      snprintf (operands[op_num], 24, "16");
7987af5a897Schristos 	      continue;
7997af5a897Schristos 
8007af5a897Schristos 	    case tic6x_operand_hw_const_24:
8017af5a897Schristos 	      operands_text[op_num] = TRUE;
8027af5a897Schristos 	      snprintf (operands[op_num], 24, "24");
8037af5a897Schristos 	      continue;
8047af5a897Schristos 
8057af5a897Schristos 	    case tic6x_operand_hw_const_31:
8067af5a897Schristos 	      operands_text[op_num] = TRUE;
8077af5a897Schristos 	      snprintf (operands[op_num], 24, "31");
8087af5a897Schristos 	      continue;
8097af5a897Schristos 
810c5dff60aSchristos 	    default:
811c5dff60aSchristos 	      break;
812c5dff60aSchristos 	    }
813c5dff60aSchristos 
814c5dff60aSchristos 	  for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
815c5dff60aSchristos 	    {
816c5dff60aSchristos 	      const tic6x_coding_field *const enc
817c5dff60aSchristos 		= &opc->variable_fields[fld_num];
818c5dff60aSchristos 	      const tic6x_insn_field *field;
819c5dff60aSchristos 	      unsigned int fld_val;
8207af5a897Schristos 	      unsigned int reg_base = 0;
821c5dff60aSchristos 	      signed int signed_fld_val;
8227af5a897Schristos               char reg_side = '?';
823c5dff60aSchristos 
824c5dff60aSchristos 	      if (enc->operand_num != op_num)
825c5dff60aSchristos 		continue;
826c5dff60aSchristos 	      field = tic6x_field_from_fmt (fmt, enc->field_id);
827c5dff60aSchristos 	      if (!field)
8287af5a897Schristos 		{
8297af5a897Schristos 		  printf ("opcode %x: missing field (field_id:%d) in format\n", opcode, enc->field_id);
830c5dff60aSchristos 		  abort ();
8317af5a897Schristos 		}
832c5dff60aSchristos               fld_val = tic6x_field_bits (opcode, field);
833c5dff60aSchristos 	      switch (enc->coding_method)
834c5dff60aSchristos 		{
8357af5a897Schristos                 case tic6x_coding_cst_s3i:
8367af5a897Schristos                   (fld_val == 0x00) && (fld_val = 0x10);
8377af5a897Schristos                   (fld_val == 0x07) && (fld_val = 0x08);
8387af5a897Schristos                   /* Fall through.  */
839c5dff60aSchristos 		case tic6x_coding_ucst:
840c5dff60aSchristos 		case tic6x_coding_ulcst_dpr_byte:
841c5dff60aSchristos 		case tic6x_coding_ulcst_dpr_half:
842c5dff60aSchristos 		case tic6x_coding_ulcst_dpr_word:
843c5dff60aSchristos 		case tic6x_coding_lcst_low16:
844c5dff60aSchristos 		  switch (opc->operand_info[op_num].form)
845c5dff60aSchristos 		    {
846c5dff60aSchristos 		    case tic6x_operand_asm_const:
847c5dff60aSchristos 		    case tic6x_operand_link_const:
848c5dff60aSchristos 		      operands_text[op_num] = TRUE;
849c5dff60aSchristos 		      snprintf (operands[op_num], 24, "%u", fld_val);
850c5dff60aSchristos 		      break;
851c5dff60aSchristos 
852c5dff60aSchristos 		    case tic6x_operand_mem_long:
853c5dff60aSchristos 		      mem_offset = fld_val;
854c5dff60aSchristos 		      mem_offset_known_long = TRUE;
855c5dff60aSchristos 		      break;
856c5dff60aSchristos 
857c5dff60aSchristos 		    default:
8587af5a897Schristos                       printf ("opcode %x: illegal operand form for operand#%d\n", opcode, op_num);
859c5dff60aSchristos 		      abort ();
860c5dff60aSchristos 		    }
861c5dff60aSchristos 		  break;
862c5dff60aSchristos 
863c5dff60aSchristos 		case tic6x_coding_lcst_high16:
864c5dff60aSchristos 		  operands_text[op_num] = TRUE;
865c5dff60aSchristos 		  snprintf (operands[op_num], 24, "%u", fld_val << 16);
866c5dff60aSchristos 		  break;
867c5dff60aSchristos 
8687af5a897Schristos                 case tic6x_coding_scst_l3i:
8697af5a897Schristos 		  operands_text[op_num] = TRUE;
8707af5a897Schristos                   if (fld_val == 0)
8717af5a897Schristos 		    {
8727af5a897Schristos 		      signed_fld_val = 8;
8737af5a897Schristos 		    }
8747af5a897Schristos 		  else
8757af5a897Schristos 		    {
8767af5a897Schristos 		      signed_fld_val = (signed int) fld_val;
8777af5a897Schristos 		      signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
8787af5a897Schristos 		      signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
8797af5a897Schristos 		    }
8807af5a897Schristos 		  snprintf (operands[op_num], 24, "%d", signed_fld_val);
8817af5a897Schristos 		  break;
8827af5a897Schristos 
883c5dff60aSchristos 		case tic6x_coding_scst:
884c5dff60aSchristos 		  operands_text[op_num] = TRUE;
885c5dff60aSchristos 		  signed_fld_val = (signed int) fld_val;
8867af5a897Schristos 		  signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
8877af5a897Schristos 		  signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
888c5dff60aSchristos 		  snprintf (operands[op_num], 24, "%d", signed_fld_val);
889c5dff60aSchristos 		  break;
890c5dff60aSchristos 
891c5dff60aSchristos 		case tic6x_coding_ucst_minus_one:
892c5dff60aSchristos 		  operands_text[op_num] = TRUE;
893c5dff60aSchristos 		  snprintf (operands[op_num], 24, "%u", fld_val + 1);
894c5dff60aSchristos 		  break;
895c5dff60aSchristos 
896c5dff60aSchristos 		case tic6x_coding_pcrel:
897c5dff60aSchristos 		case tic6x_coding_pcrel_half:
898c5dff60aSchristos 		  signed_fld_val = (signed int) fld_val;
8997af5a897Schristos 		  signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
9007af5a897Schristos 		  signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
901c5dff60aSchristos 		  if (fetch_packet_header_based
902c5dff60aSchristos 		      && enc->coding_method == tic6x_coding_pcrel_half)
903c5dff60aSchristos 		    signed_fld_val *= 2;
904c5dff60aSchristos 		  else
905c5dff60aSchristos 		    signed_fld_val *= 4;
906c5dff60aSchristos 		  operands_pcrel[op_num] = TRUE;
907c5dff60aSchristos 		  operands_addresses[op_num] = fp_addr + signed_fld_val;
908c5dff60aSchristos 		  break;
909c5dff60aSchristos 
9107af5a897Schristos 		case tic6x_coding_regpair_msb:
9117af5a897Schristos 		  if (opc->operand_info[op_num].form != tic6x_operand_regpair)
9127af5a897Schristos 		    abort ();
9137af5a897Schristos 		  operands_text[op_num] = TRUE;
9147af5a897Schristos 		  snprintf (operands[op_num], 24, "%c%u:%c%u",
9157af5a897Schristos 			    (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1),
9167af5a897Schristos 			    (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1) - 1);
9177af5a897Schristos 		  break;
9187af5a897Schristos 
9197af5a897Schristos 		case tic6x_coding_pcrel_half_unsigned:
9207af5a897Schristos 		  operands_pcrel[op_num] = TRUE;
9217af5a897Schristos 		  operands_addresses[op_num] = fp_addr + 2 * fld_val;
9227af5a897Schristos 		  break;
9237af5a897Schristos 
924c5dff60aSchristos 		case tic6x_coding_reg_shift:
925c5dff60aSchristos 		  fld_val <<= 1;
926c5dff60aSchristos 		  /* Fall through.  */
927c5dff60aSchristos 		case tic6x_coding_reg:
9287af5a897Schristos                   if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS))
9297af5a897Schristos                     {
9307af5a897Schristos 		      reg_base = 16;
9317af5a897Schristos                     }
932c5dff60aSchristos 		  switch (opc->operand_info[op_num].form)
933c5dff60aSchristos 		    {
9347af5a897Schristos 		    case tic6x_operand_treg:
9357af5a897Schristos                       if (!have_t)
9367af5a897Schristos 			{
9377af5a897Schristos 			  printf ("opcode %x: operand treg but missing t field\n", opcode);
9387af5a897Schristos 			  abort ();
9397af5a897Schristos 			}
9407af5a897Schristos 		      operands_text[op_num] = TRUE;
9417af5a897Schristos                       reg_side = t_val ? 'b' : 'a';
9427af5a897Schristos 		      snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
9437af5a897Schristos 		      break;
9447af5a897Schristos 
945c5dff60aSchristos 		    case tic6x_operand_reg:
946c5dff60aSchristos 		      operands_text[op_num] = TRUE;
9477af5a897Schristos                       reg_side = (func_unit_side == 2) ? 'b' : 'a';
9487af5a897Schristos 		      snprintf (operands[op_num], 24, "%c%u", reg_side,  reg_base + fld_val);
9497af5a897Schristos 		      break;
9507af5a897Schristos 
9517af5a897Schristos 		    case tic6x_operand_reg_nors:
9527af5a897Schristos 		      operands_text[op_num] = TRUE;
9537af5a897Schristos                       reg_side = (func_unit_side == 2) ? 'b' : 'a';
9547af5a897Schristos 		      snprintf (operands[op_num], 24, "%c%u", reg_side, fld_val);
9557af5a897Schristos 		      break;
9567af5a897Schristos 
9577af5a897Schristos 		    case tic6x_operand_reg_bside:
9587af5a897Schristos 		      operands_text[op_num] = TRUE;
9597af5a897Schristos 		      snprintf (operands[op_num], 24, "b%u", reg_base + fld_val);
9607af5a897Schristos 		      break;
9617af5a897Schristos 
9627af5a897Schristos 		    case tic6x_operand_reg_bside_nors:
9637af5a897Schristos 		      operands_text[op_num] = TRUE;
9647af5a897Schristos 		      snprintf (operands[op_num], 24, "b%u", fld_val);
965c5dff60aSchristos 		      break;
966c5dff60aSchristos 
967c5dff60aSchristos 		    case tic6x_operand_xreg:
968c5dff60aSchristos 		      operands_text[op_num] = TRUE;
9697af5a897Schristos                       reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a';
9707af5a897Schristos 		      snprintf (operands[op_num], 24, "%c%u", reg_side,  reg_base + fld_val);
971c5dff60aSchristos 		      break;
972c5dff60aSchristos 
973c5dff60aSchristos 		    case tic6x_operand_dreg:
974c5dff60aSchristos 		      operands_text[op_num] = TRUE;
9757af5a897Schristos                       reg_side = (func_unit_data_side == 2) ? 'b' : 'a';
9767af5a897Schristos 		      snprintf (operands[op_num], 24, "%c%u", reg_side,  reg_base + fld_val);
977c5dff60aSchristos 		      break;
978c5dff60aSchristos 
979c5dff60aSchristos 		    case tic6x_operand_regpair:
980c5dff60aSchristos 		      operands_text[op_num] = TRUE;
981c5dff60aSchristos 		      if (fld_val & 1)
982c5dff60aSchristos 			operands_ok = FALSE;
9837af5a897Schristos                       reg_side = (func_unit_side == 2) ? 'b' : 'a';
984c5dff60aSchristos 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
9857af5a897Schristos                                 reg_side, reg_base + fld_val + 1,
9867af5a897Schristos 				reg_side, reg_base + fld_val);
987c5dff60aSchristos 		      break;
988c5dff60aSchristos 
989c5dff60aSchristos 		    case tic6x_operand_xregpair:
990c5dff60aSchristos 		      operands_text[op_num] = TRUE;
991c5dff60aSchristos 		      if (fld_val & 1)
992c5dff60aSchristos 			operands_ok = FALSE;
9937af5a897Schristos                       reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a';
994c5dff60aSchristos 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
9957af5a897Schristos 				reg_side, reg_base + fld_val + 1,
9967af5a897Schristos 				reg_side, reg_base + fld_val);
9977af5a897Schristos 		      break;
9987af5a897Schristos 
9997af5a897Schristos 		    case tic6x_operand_tregpair:
10007af5a897Schristos                       if (!have_t)
10017af5a897Schristos 			{
10027af5a897Schristos 			  printf ("opcode %x: operand tregpair but missing t field\n", opcode);
10037af5a897Schristos 			  abort ();
10047af5a897Schristos 			}
10057af5a897Schristos 		      operands_text[op_num] = TRUE;
10067af5a897Schristos 		      if (fld_val & 1)
10077af5a897Schristos 			operands_ok = FALSE;
10087af5a897Schristos                       reg_side = t_val ? 'b' : 'a';
10097af5a897Schristos 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
10107af5a897Schristos 				reg_side, reg_base + fld_val + 1,
10117af5a897Schristos 				reg_side, reg_base + fld_val);
1012c5dff60aSchristos 		      break;
1013c5dff60aSchristos 
1014c5dff60aSchristos 		    case tic6x_operand_dregpair:
1015c5dff60aSchristos 		      operands_text[op_num] = TRUE;
1016c5dff60aSchristos 		      if (fld_val & 1)
1017c5dff60aSchristos 			operands_ok = FALSE;
10187af5a897Schristos                       reg_side = (func_unit_data_side) == 2 ? 'b' : 'a';
1019c5dff60aSchristos 		      snprintf (operands[op_num], 24, "%c%u:%c%u",
10207af5a897Schristos 				reg_side, reg_base + fld_val + 1,
10217af5a897Schristos 				reg_side, reg_base + fld_val);
1022c5dff60aSchristos 		      break;
1023c5dff60aSchristos 
1024c5dff60aSchristos 		    case tic6x_operand_mem_deref:
1025c5dff60aSchristos 		      operands_text[op_num] = TRUE;
10267af5a897Schristos                       reg_side = func_unit_side == 2 ? 'b' : 'a';
10277af5a897Schristos 		      snprintf (operands[op_num], 24, "*%c%u", reg_side, reg_base + fld_val);
1028c5dff60aSchristos 		      break;
1029c5dff60aSchristos 
1030c5dff60aSchristos 		    case tic6x_operand_mem_short:
1031c5dff60aSchristos 		    case tic6x_operand_mem_ndw:
1032c5dff60aSchristos 		      mem_base_reg = fld_val;
1033c5dff60aSchristos 		      mem_base_reg_known = TRUE;
1034c5dff60aSchristos 		      break;
1035c5dff60aSchristos 
1036c5dff60aSchristos 		    default:
10377af5a897Schristos                       printf ("opcode %x: unexpected operand form %d for operand #%d",
10387af5a897Schristos 			      opcode, opc->operand_info[op_num].form, op_num);
10397af5a897Schristos 		      abort ();
10407af5a897Schristos 		    }
10417af5a897Schristos 		  break;
10427af5a897Schristos 
10437af5a897Schristos                 case tic6x_coding_reg_ptr:
10447af5a897Schristos 		  switch (opc->operand_info[op_num].form)
10457af5a897Schristos 		    {
10467af5a897Schristos 		    case tic6x_operand_mem_short:
10477af5a897Schristos 		    case tic6x_operand_mem_ndw:
10487af5a897Schristos                       if (fld_val > 0x3u)
10497af5a897Schristos 			{
10507af5a897Schristos 			  printf("opcode %x: illegal field value for ptr register of operand #%d (%d)",
10517af5a897Schristos 				 opcode, op_num, fld_val);
10527af5a897Schristos 			  abort ();
10537af5a897Schristos 			}
10547af5a897Schristos 		      mem_base_reg = 0x4 | fld_val;
10557af5a897Schristos 		      mem_base_reg_known = TRUE;
10567af5a897Schristos 		      break;
10577af5a897Schristos 
10587af5a897Schristos 		    default:
10597af5a897Schristos                       printf ("opcode %x: unexpected operand form %d for operand #%d",
10607af5a897Schristos 			      opcode, opc->operand_info[op_num].form, op_num);
1061c5dff60aSchristos 		      abort ();
1062c5dff60aSchristos 		    }
1063c5dff60aSchristos 		  break;
1064c5dff60aSchristos 
1065c5dff60aSchristos 		case tic6x_coding_areg:
1066c5dff60aSchristos 		  switch (opc->operand_info[op_num].form)
1067c5dff60aSchristos 		    {
1068c5dff60aSchristos 		    case tic6x_operand_areg:
1069c5dff60aSchristos 		      operands_text[op_num] = TRUE;
1070c5dff60aSchristos 		      snprintf (operands[op_num], 24, "b%u",
1071c5dff60aSchristos 				fld_val ? 15u : 14u);
1072c5dff60aSchristos 		      break;
1073c5dff60aSchristos 
1074c5dff60aSchristos 		    case tic6x_operand_mem_long:
1075c5dff60aSchristos 		      mem_base_reg = fld_val ? 15u : 14u;
1076c5dff60aSchristos 		      mem_base_reg_known_long = TRUE;
1077c5dff60aSchristos 		      break;
1078c5dff60aSchristos 
1079c5dff60aSchristos 		    default:
10807af5a897Schristos                       printf ("opcode %x: bad operand form\n", opcode);
1081c5dff60aSchristos 		      abort ();
1082c5dff60aSchristos 		    }
1083c5dff60aSchristos 		  break;
1084c5dff60aSchristos 
10857af5a897Schristos 		case tic6x_coding_mem_offset_minus_one_noscale:
10867af5a897Schristos 		case tic6x_coding_mem_offset_minus_one:
10877af5a897Schristos 		  fld_val += 1;
10881c468f90Schristos 		  /* Fall through.  */
1089c5dff60aSchristos 		case tic6x_coding_mem_offset_noscale:
10907af5a897Schristos 		case tic6x_coding_mem_offset:
1091c5dff60aSchristos 		  mem_offset = fld_val;
1092c5dff60aSchristos 		  mem_offset_known = TRUE;
10937af5a897Schristos 		  if (num_bits == 16)
10947af5a897Schristos 		    {
10957af5a897Schristos 		      mem_mode_known = TRUE;
10967af5a897Schristos 		      mem_mode = TIC6X_INSN16_MEM_MODE_VAL (opc->flags);
10977af5a897Schristos 		      mem_scaled_known = TRUE;
10987af5a897Schristos 		      mem_scaled = TRUE;
10997af5a897Schristos 		      if (opc->flags & TIC6X_FLAG_INSN16_B15PTR)
11007af5a897Schristos 			{
11017af5a897Schristos 			  mem_base_reg_known = TRUE;
11027af5a897Schristos 			  mem_base_reg = 15;
11037af5a897Schristos 			}
11047af5a897Schristos 		      if ( enc->coding_method == tic6x_coding_mem_offset_noscale
11057af5a897Schristos 			   || enc->coding_method == tic6x_coding_mem_offset_noscale )
11067af5a897Schristos 			mem_scaled = FALSE;
11077af5a897Schristos 		    }
1108c5dff60aSchristos 		  break;
1109c5dff60aSchristos 
1110c5dff60aSchristos 		case tic6x_coding_mem_mode:
1111c5dff60aSchristos 		  mem_mode = fld_val;
1112c5dff60aSchristos 		  mem_mode_known = TRUE;
1113c5dff60aSchristos 		  break;
1114c5dff60aSchristos 
1115c5dff60aSchristos 		case tic6x_coding_scaled:
1116c5dff60aSchristos 		  mem_scaled = fld_val;
1117c5dff60aSchristos 		  mem_scaled_known = TRUE;
1118c5dff60aSchristos 		  break;
1119c5dff60aSchristos 
1120c5dff60aSchristos 		case tic6x_coding_crlo:
1121c5dff60aSchristos 		  crlo = fld_val;
1122c5dff60aSchristos 		  crlo_known = TRUE;
1123c5dff60aSchristos 		  break;
1124c5dff60aSchristos 
1125c5dff60aSchristos 		case tic6x_coding_crhi:
1126c5dff60aSchristos 		  crhi = fld_val;
1127c5dff60aSchristos 		  crhi_known = TRUE;
1128c5dff60aSchristos 		  break;
1129c5dff60aSchristos 
1130c5dff60aSchristos 		case tic6x_coding_fstg:
1131c5dff60aSchristos 		case tic6x_coding_fcyc:
1132c5dff60aSchristos 		  if (!prev_sploop_found)
1133c5dff60aSchristos 		    {
1134c5dff60aSchristos 		      bfd_vma search_fp_addr = fp_addr;
1135c5dff60aSchristos 		      bfd_vma search_fp_offset = fp_offset;
1136c5dff60aSchristos 		      bfd_boolean search_fp_header_based
1137c5dff60aSchristos 			= fetch_packet_header_based;
1138c5dff60aSchristos 		      tic6x_fetch_packet_header search_fp_header = header;
1139c5dff60aSchristos 		      unsigned char search_fp[32];
1140c5dff60aSchristos 		      unsigned int search_num_bits;
1141c5dff60aSchristos 		      unsigned int search_opcode;
1142c5dff60aSchristos 		      unsigned int sploop_ii = 0;
1143c5dff60aSchristos 		      int i;
1144c5dff60aSchristos 
1145c5dff60aSchristos 		      memcpy (search_fp, fp, 32);
1146c5dff60aSchristos 
1147c5dff60aSchristos 		      /* To interpret these bits in an SPKERNEL
1148c5dff60aSchristos 			 instruction, we must find the previous
1149c5dff60aSchristos 			 SPLOOP-family instruction.  It may come up to
1150c5dff60aSchristos 			 48 execute packets earlier.  */
1151c5dff60aSchristos 		      for (i = 0; i < 48 * 8; i++)
1152c5dff60aSchristos 			{
1153c5dff60aSchristos 			  /* Find the previous instruction.  */
1154c5dff60aSchristos 			  if (search_fp_offset & 2)
1155c5dff60aSchristos 			    search_fp_offset -= 2;
1156c5dff60aSchristos 			  else if (search_fp_offset >= 4)
1157c5dff60aSchristos 			    {
1158c5dff60aSchristos 			      if (search_fp_header_based
1159c5dff60aSchristos 				  && (search_fp_header.word_compact
1160c5dff60aSchristos 				      [(search_fp_offset >> 2) - 1]))
1161c5dff60aSchristos 				search_fp_offset -= 2;
1162c5dff60aSchristos 			      else
1163c5dff60aSchristos 				search_fp_offset -= 4;
1164c5dff60aSchristos 			    }
1165c5dff60aSchristos 			  else
1166c5dff60aSchristos 			    {
1167c5dff60aSchristos 			      search_fp_addr -= 32;
1168c5dff60aSchristos 			      status = info->read_memory_func (search_fp_addr,
1169c5dff60aSchristos 							       search_fp,
1170c5dff60aSchristos 							       32, info);
1171c5dff60aSchristos 			      if (status)
1172c5dff60aSchristos 				/* No previous SPLOOP instruction.  */
1173c5dff60aSchristos 				break;
1174c5dff60aSchristos 			      search_fp_header_based
1175c5dff60aSchristos 				= (tic6x_check_fetch_packet_header
1176c5dff60aSchristos 				   (search_fp, &search_fp_header, info));
1177c5dff60aSchristos 			      if (search_fp_header_based)
1178c5dff60aSchristos 				search_fp_offset
1179c5dff60aSchristos 				  = search_fp_header.word_compact[6] ? 26 : 24;
1180c5dff60aSchristos 			      else
1181c5dff60aSchristos 				search_fp_offset = 28;
1182c5dff60aSchristos 			    }
1183c5dff60aSchristos 
1184c5dff60aSchristos 			  /* Extract the previous instruction.  */
1185c5dff60aSchristos 			  if (search_fp_header_based)
1186c5dff60aSchristos 			    search_num_bits
1187c5dff60aSchristos 			      = (search_fp_header.word_compact[search_fp_offset
1188c5dff60aSchristos 							       >> 2]
1189c5dff60aSchristos 				 ? 16
1190c5dff60aSchristos 				 : 32);
1191c5dff60aSchristos 			  else
1192c5dff60aSchristos 			    search_num_bits = 32;
1193c5dff60aSchristos 			  if (search_num_bits == 16)
1194c5dff60aSchristos 			    {
1195c5dff60aSchristos 			      if (info->endian == BFD_ENDIAN_LITTLE)
1196c5dff60aSchristos 				search_opcode
1197c5dff60aSchristos 				  = (tic6x_extract_16
11987af5a897Schristos 				     (search_fp + search_fp_offset, &header, info));
1199c5dff60aSchristos 			      else
1200c5dff60aSchristos 				search_opcode
1201c5dff60aSchristos 				  = (tic6x_extract_16
12027af5a897Schristos 				     (search_fp + (search_fp_offset ^ 2), &header,
1203c5dff60aSchristos 				      info));
1204c5dff60aSchristos 			    }
1205c5dff60aSchristos 			  else
1206c5dff60aSchristos 			    search_opcode
1207c5dff60aSchristos 			      = tic6x_extract_32 (search_fp + search_fp_offset,
1208c5dff60aSchristos 						  info);
1209c5dff60aSchristos 
1210c5dff60aSchristos 			  /* Check whether it is an SPLOOP-family
1211c5dff60aSchristos 			     instruction.  */
1212c5dff60aSchristos 			  if (search_num_bits == 32
1213c5dff60aSchristos 			      && ((search_opcode & 0x003ffffe) == 0x00038000
1214c5dff60aSchristos 				  || (search_opcode & 0x003ffffe) == 0x0003a000
1215c5dff60aSchristos 				  || ((search_opcode & 0x003ffffe)
1216c5dff60aSchristos 				      == 0x0003e000)))
1217c5dff60aSchristos 			    {
1218c5dff60aSchristos 			      prev_sploop_found = TRUE;
1219c5dff60aSchristos 			      sploop_ii = ((search_opcode >> 23) & 0x1f) + 1;
1220c5dff60aSchristos 			    }
1221c5dff60aSchristos 			  else if (search_num_bits == 16
1222c5dff60aSchristos 				   && (search_opcode & 0x3c7e) == 0x0c66)
1223c5dff60aSchristos 			    {
1224c5dff60aSchristos 			      prev_sploop_found = TRUE;
1225c5dff60aSchristos 			      sploop_ii
1226c5dff60aSchristos 				= (((search_opcode >> 7) & 0x7)
1227c5dff60aSchristos 				   | ((search_opcode >> 11) & 0x8)) + 1;
1228c5dff60aSchristos 			    }
1229c5dff60aSchristos 			  if (prev_sploop_found)
1230c5dff60aSchristos 			    {
1231c5dff60aSchristos 			      if (sploop_ii <= 0)
12327af5a897Schristos 				{
12337af5a897Schristos 				  printf ("opcode %x:  sloop index not found (%d)\n", opcode, sploop_ii);
1234c5dff60aSchristos 				  abort ();
12357af5a897Schristos 				}
1236c5dff60aSchristos 			      else if (sploop_ii <= 1)
1237c5dff60aSchristos 				fcyc_bits = 0;
1238c5dff60aSchristos 			      else if (sploop_ii <= 2)
1239c5dff60aSchristos 				fcyc_bits = 1;
1240c5dff60aSchristos 			      else if (sploop_ii <= 4)
1241c5dff60aSchristos 				fcyc_bits = 2;
1242c5dff60aSchristos 			      else if (sploop_ii <= 8)
1243c5dff60aSchristos 				fcyc_bits = 3;
1244c5dff60aSchristos 			      else if (sploop_ii <= 14)
1245c5dff60aSchristos 				fcyc_bits = 4;
1246c5dff60aSchristos 			      else
1247c5dff60aSchristos 				prev_sploop_found = FALSE;
1248c5dff60aSchristos 			    }
1249c5dff60aSchristos 			  if (prev_sploop_found)
1250c5dff60aSchristos 			    break;
1251c5dff60aSchristos 			}
1252c5dff60aSchristos 		    }
1253c5dff60aSchristos 		  if (!prev_sploop_found)
1254c5dff60aSchristos 		    {
1255c5dff60aSchristos 		      operands_ok = FALSE;
1256c5dff60aSchristos 		      operands_text[op_num] = TRUE;
1257c5dff60aSchristos 		      break;
1258c5dff60aSchristos 		    }
12597af5a897Schristos 		  if (fcyc_bits > tic6x_field_width(field))
12607af5a897Schristos 		    {
12617af5a897Schristos 		      printf ("opcode %x: illegal fcyc value (%d)\n", opcode, fcyc_bits);
1262c5dff60aSchristos 		      abort ();
12637af5a897Schristos 		    }
1264c5dff60aSchristos 		  if (enc->coding_method == tic6x_coding_fstg)
1265c5dff60aSchristos 		    {
1266c5dff60aSchristos 		      int i, t;
1267c5dff60aSchristos 		      for (t = 0, i = fcyc_bits; i < 6; i++)
1268c5dff60aSchristos 			t = (t << 1) | ((fld_val >> i) & 1);
1269c5dff60aSchristos 		      operands_text[op_num] = TRUE;
1270c5dff60aSchristos 		      snprintf (operands[op_num], 24, "%u", t);
1271c5dff60aSchristos 		    }
1272c5dff60aSchristos 		  else
1273c5dff60aSchristos 		    {
1274c5dff60aSchristos 		      operands_text[op_num] = TRUE;
1275c5dff60aSchristos 		      snprintf (operands[op_num], 24, "%u",
1276c5dff60aSchristos 				fld_val & ((1 << fcyc_bits) - 1));
1277c5dff60aSchristos 		    }
1278c5dff60aSchristos 		  break;
1279c5dff60aSchristos 
1280c5dff60aSchristos 		case tic6x_coding_spmask:
1281c5dff60aSchristos 		  if (fld_val == 0)
1282c5dff60aSchristos 		    spmask_skip_operand = TRUE;
1283c5dff60aSchristos 		  else
1284c5dff60aSchristos 		    {
1285c5dff60aSchristos 		      char *p;
1286c5dff60aSchristos 		      unsigned int i;
1287c5dff60aSchristos 
1288c5dff60aSchristos 		      operands_text[op_num] = TRUE;
1289c5dff60aSchristos 		      p = operands[op_num];
1290c5dff60aSchristos 		      for (i = 0; i < 8; i++)
1291c5dff60aSchristos 			if (fld_val & (1 << i))
1292c5dff60aSchristos 			  {
1293c5dff60aSchristos 			    *p++ = "LSDM"[i/2];
1294c5dff60aSchristos 			    *p++ = '1' + (i & 1);
1295c5dff60aSchristos 			    *p++ = ',';
1296c5dff60aSchristos 			  }
1297c5dff60aSchristos 		      p[-1] = 0;
1298c5dff60aSchristos 		    }
1299c5dff60aSchristos 		  break;
1300c5dff60aSchristos 
1301c5dff60aSchristos 		case tic6x_coding_fu:
1302c5dff60aSchristos 		case tic6x_coding_data_fu:
1303c5dff60aSchristos 		case tic6x_coding_xpath:
13047af5a897Schristos 		case tic6x_coding_rside:
1305c5dff60aSchristos 		  /* Don't relate to operands, so operand number is
1306c5dff60aSchristos 		     meaningless.  */
1307c5dff60aSchristos 		  break;
1308c5dff60aSchristos 
1309c5dff60aSchristos 		default:
13107af5a897Schristos                   printf ("opcode %x: illegal field encoding (%d)\n", opcode, enc->coding_method);
1311c5dff60aSchristos 		  abort ();
1312c5dff60aSchristos 		}
1313c5dff60aSchristos 
1314c5dff60aSchristos 	      if (mem_base_reg_known_long && mem_offset_known_long)
1315c5dff60aSchristos 		{
1316c5dff60aSchristos 		  if (operands_text[op_num] || operands_pcrel[op_num])
13177af5a897Schristos 		    {
13187af5a897Schristos 		      printf ("opcode %x: long access but operands already known ?\n", opcode);
1319c5dff60aSchristos 		      abort ();
13207af5a897Schristos 		    }
1321c5dff60aSchristos 		  operands_text[op_num] = TRUE;
1322c5dff60aSchristos 		  snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg,
1323c5dff60aSchristos 			    mem_offset * opc->operand_info[op_num].size);
1324c5dff60aSchristos 		}
1325c5dff60aSchristos 
1326c5dff60aSchristos 	      if (mem_base_reg_known && mem_offset_known && mem_mode_known
1327c5dff60aSchristos 		  && (mem_scaled_known
1328c5dff60aSchristos 		      || (opc->operand_info[op_num].form
1329c5dff60aSchristos 			  != tic6x_operand_mem_ndw)))
1330c5dff60aSchristos 		{
1331c5dff60aSchristos 		  char side;
1332c5dff60aSchristos 		  char base[4];
1333c5dff60aSchristos 		  bfd_boolean offset_is_reg;
1334c5dff60aSchristos 		  bfd_boolean offset_scaled;
1335c5dff60aSchristos 		  char offset[4];
1336c5dff60aSchristos 		  char offsetp[6];
1337c5dff60aSchristos 
1338c5dff60aSchristos 		  if (operands_text[op_num] || operands_pcrel[op_num])
13397af5a897Schristos 		    {
13407af5a897Schristos 		      printf ("opcode %x: mem access operands already known ?\n", opcode);
1341c5dff60aSchristos 		      abort ();
13427af5a897Schristos 		    }
1343c5dff60aSchristos 
1344c5dff60aSchristos 		  side = func_unit_side == 2 ? 'b' : 'a';
1345c5dff60aSchristos 		  snprintf (base, 4, "%c%u", side, mem_base_reg);
1346c5dff60aSchristos 
1347c5dff60aSchristos 		  offset_is_reg = ((mem_mode & 4) ? TRUE : FALSE);
1348c5dff60aSchristos 		  if (offset_is_reg)
1349c5dff60aSchristos 		    {
13507af5a897Schristos 
13517af5a897Schristos 		      if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS))
13527af5a897Schristos 			{
13537af5a897Schristos 			  reg_base = 16;
13547af5a897Schristos 			}
13557af5a897Schristos 		      snprintf (offset, 4, "%c%u", side, reg_base + mem_offset);
1356c5dff60aSchristos 		      if (opc->operand_info[op_num].form
1357c5dff60aSchristos 			  == tic6x_operand_mem_ndw)
1358c5dff60aSchristos 			offset_scaled = mem_scaled ? TRUE : FALSE;
1359c5dff60aSchristos 		      else
1360c5dff60aSchristos 			offset_scaled = TRUE;
1361c5dff60aSchristos 		    }
1362c5dff60aSchristos 		  else
1363c5dff60aSchristos 		    {
1364c5dff60aSchristos 		      if (opc->operand_info[op_num].form
1365c5dff60aSchristos 			  == tic6x_operand_mem_ndw)
1366c5dff60aSchristos 			{
1367c5dff60aSchristos 			  offset_scaled = mem_scaled ? TRUE : FALSE;
1368c5dff60aSchristos 			  snprintf (offset, 4, "%u", mem_offset);
1369c5dff60aSchristos 			}
1370c5dff60aSchristos 		      else
1371c5dff60aSchristos 			{
1372c5dff60aSchristos 			  offset_scaled = FALSE;
1373c5dff60aSchristos 			  snprintf (offset, 4, "%u",
1374c5dff60aSchristos 				    (mem_offset
1375c5dff60aSchristos 				     * opc->operand_info[op_num].size));
1376c5dff60aSchristos 			}
1377c5dff60aSchristos 		    }
1378c5dff60aSchristos 
1379c5dff60aSchristos 		  if (offset_scaled)
1380c5dff60aSchristos 		    snprintf (offsetp, 6, "[%s]", offset);
1381c5dff60aSchristos 		  else
1382c5dff60aSchristos 		    snprintf (offsetp, 6, "(%s)", offset);
1383c5dff60aSchristos 
1384c5dff60aSchristos 		  operands_text[op_num] = TRUE;
1385c5dff60aSchristos 		  switch (mem_mode & ~4u)
1386c5dff60aSchristos 		    {
1387c5dff60aSchristos 		    case 0:
1388c5dff60aSchristos 		      snprintf (operands[op_num], 24, "*-%s%s", base, offsetp);
1389c5dff60aSchristos 		      break;
1390c5dff60aSchristos 
1391c5dff60aSchristos 		    case 1:
1392c5dff60aSchristos 		      snprintf (operands[op_num], 24, "*+%s%s", base, offsetp);
1393c5dff60aSchristos 		      break;
1394c5dff60aSchristos 
1395c5dff60aSchristos 		    case 2:
1396c5dff60aSchristos 		    case 3:
1397c5dff60aSchristos 		      operands_ok = FALSE;
1398c5dff60aSchristos 		      break;
1399c5dff60aSchristos 
1400c5dff60aSchristos 		    case 8:
1401c5dff60aSchristos 		      snprintf (operands[op_num], 24, "*--%s%s", base,
1402c5dff60aSchristos 				offsetp);
1403c5dff60aSchristos 		      break;
1404c5dff60aSchristos 
1405c5dff60aSchristos 		    case 9:
1406c5dff60aSchristos 		      snprintf (operands[op_num], 24, "*++%s%s", base,
1407c5dff60aSchristos 				offsetp);
1408c5dff60aSchristos 		      break;
1409c5dff60aSchristos 
1410c5dff60aSchristos 		    case 10:
1411c5dff60aSchristos 		      snprintf (operands[op_num], 24, "*%s--%s", base,
1412c5dff60aSchristos 				offsetp);
1413c5dff60aSchristos 		      break;
1414c5dff60aSchristos 
1415c5dff60aSchristos 		    case 11:
1416c5dff60aSchristos 		      snprintf (operands[op_num], 24, "*%s++%s", base,
1417c5dff60aSchristos 				offsetp);
1418c5dff60aSchristos 		      break;
1419c5dff60aSchristos 
1420c5dff60aSchristos 		    default:
14217af5a897Schristos                       printf ("*** unknown mem_mode : %d \n", mem_mode);
1422c5dff60aSchristos 		      abort ();
1423c5dff60aSchristos 		    }
1424c5dff60aSchristos 		}
1425c5dff60aSchristos 
1426c5dff60aSchristos 	      if (crlo_known && crhi_known)
1427c5dff60aSchristos 		{
1428c5dff60aSchristos 		  tic6x_rw rw;
1429c5dff60aSchristos 		  tic6x_ctrl_id crid;
1430c5dff60aSchristos 
1431c5dff60aSchristos 		  if (operands_text[op_num] || operands_pcrel[op_num])
14327af5a897Schristos 		    {
14337af5a897Schristos 		      printf ("*** abort crlo crli\n");
1434c5dff60aSchristos 		      abort ();
14357af5a897Schristos 		    }
1436c5dff60aSchristos 
1437c5dff60aSchristos 		  rw = opc->operand_info[op_num].rw;
1438c5dff60aSchristos 		  if (rw != tic6x_rw_read
1439c5dff60aSchristos 		      && rw != tic6x_rw_write)
14407af5a897Schristos 		    {
14417af5a897Schristos 		      printf ("*** abort rw : %d\n", rw);
1442c5dff60aSchristos 		      abort ();
14437af5a897Schristos 		    }
1444c5dff60aSchristos 
1445c5dff60aSchristos 		  for (crid = 0; crid < tic6x_ctrl_max; crid++)
1446c5dff60aSchristos 		    {
1447c5dff60aSchristos 		      if (crlo == tic6x_ctrl_table[crid].crlo
1448c5dff60aSchristos 			  && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0
1449c5dff60aSchristos 			  && (rw == tic6x_rw_read
1450c5dff60aSchristos 			      ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read
1451c5dff60aSchristos 				 || (tic6x_ctrl_table[crid].rw
1452c5dff60aSchristos 				     == tic6x_rw_read_write))
1453c5dff60aSchristos 			      : (tic6x_ctrl_table[crid].rw == tic6x_rw_write
1454c5dff60aSchristos 				 || (tic6x_ctrl_table[crid].rw
1455c5dff60aSchristos 				     == tic6x_rw_read_write))))
1456c5dff60aSchristos 			break;
1457c5dff60aSchristos 		    }
1458c5dff60aSchristos 		  if (crid == tic6x_ctrl_max)
1459c5dff60aSchristos 		    {
1460c5dff60aSchristos 		      operands_text[op_num] = TRUE;
1461c5dff60aSchristos 		      operands_ok = FALSE;
1462c5dff60aSchristos 		    }
1463c5dff60aSchristos 		  else
1464c5dff60aSchristos 		    {
1465c5dff60aSchristos 		      operands_text[op_num] = TRUE;
1466c5dff60aSchristos 		      snprintf (operands[op_num], 24, "%s",
1467c5dff60aSchristos 				tic6x_ctrl_table[crid].name);
1468c5dff60aSchristos 		    }
1469c5dff60aSchristos 		}
1470c5dff60aSchristos 
1471c5dff60aSchristos 	      if (operands_text[op_num] || operands_pcrel[op_num]
1472c5dff60aSchristos 		  || spmask_skip_operand)
1473c5dff60aSchristos 		break;
1474c5dff60aSchristos 	    }
14757af5a897Schristos           /* end for fld_num */
14767af5a897Schristos 
1477c5dff60aSchristos 	  if (spmask_skip_operand)
1478c5dff60aSchristos 	    {
1479c5dff60aSchristos 	      /* SPMASK operands are only valid as the single operand
1480c5dff60aSchristos 		 in the opcode table.  */
1481c5dff60aSchristos 	      if (num_operands != 1)
14827af5a897Schristos 		{
14837af5a897Schristos 		  printf ("opcode: %x, num_operands != 1 : %d\n", opcode, num_operands);
1484c5dff60aSchristos 		  abort ();
14857af5a897Schristos 		}
1486c5dff60aSchristos 	      num_operands = 0;
1487c5dff60aSchristos 	      break;
1488c5dff60aSchristos 	    }
14897af5a897Schristos 
1490c5dff60aSchristos 	  /* The operand must by now have been decoded.  */
1491c5dff60aSchristos 	  if (!operands_text[op_num] && !operands_pcrel[op_num])
14927af5a897Schristos             {
14937af5a897Schristos               printf ("opcode: %x, operand #%d not decoded\n", opcode, op_num);
1494c5dff60aSchristos               abort ();
1495c5dff60aSchristos             }
14967af5a897Schristos         }
14977af5a897Schristos       /* end for op_num */
1498c5dff60aSchristos 
1499c5dff60aSchristos       if (!operands_ok)
1500c5dff60aSchristos 	continue;
1501c5dff60aSchristos 
1502c5dff60aSchristos       info->bytes_per_chunk = num_bits / 8;
15037af5a897Schristos       info->fprintf_func (info->stream, "%s", parallel);
15047af5a897Schristos       info->fprintf_func (info->stream, "%s%s%s", cond, opc->name,
15057af5a897Schristos                           func_unit);
1506c5dff60aSchristos       for (op_num = 0; op_num < num_operands; op_num++)
1507c5dff60aSchristos 	{
1508c5dff60aSchristos 	  info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ','));
1509c5dff60aSchristos 	  if (operands_pcrel[op_num])
1510c5dff60aSchristos 	    info->print_address_func (operands_addresses[op_num], info);
1511c5dff60aSchristos 	  else
1512c5dff60aSchristos 	    info->fprintf_func (info->stream, "%s", operands[op_num]);
1513c5dff60aSchristos 	}
1514c5dff60aSchristos       if (fetch_packet_header_based && header.prot)
1515c5dff60aSchristos 	info->fprintf_func (info->stream, " || nop 5");
1516c5dff60aSchristos 
1517c5dff60aSchristos       return num_bits / 8;
1518c5dff60aSchristos     }
1519c5dff60aSchristos 
1520c5dff60aSchristos   info->bytes_per_chunk = num_bits / 8;
1521c5dff60aSchristos   info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>",
1522c5dff60aSchristos 		      (int) num_bits / 4, opcode);
1523c5dff60aSchristos   return num_bits / 8;
1524c5dff60aSchristos }
1525