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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [opcodes/] [tic6x-dis.c] - Blame information for rev 858

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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