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