OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [opcodes/] [tic6x-dis.c] - Blame information for rev 18

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.