Coverage Report

Created: 2023-08-28 06:23

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