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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [opcodes/] [tic54x-dis.c] - Blame information for rev 853

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

Line No. Rev Author Line
1 38 julius
/* Disassembly routines for TMS320C54X architecture
2
   Copyright 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
3
   Contributed by Timothy Wall (twall@cygnus.com)
4
 
5
   This file is part of the GNU opcodes library.
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, or (at your option)
10
   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 file; see the file COPYING.  If not, write to the
19
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#include <errno.h>
23
#include <math.h>
24
#include <stdlib.h>
25
#include "sysdep.h"
26
#include "dis-asm.h"
27
#include "opcode/tic54x.h"
28
#include "coff/tic54x.h"
29
 
30
static int has_lkaddr (unsigned short, const template *);
31
static int get_insn_size (unsigned short, const template *);
32
static int print_instruction (disassemble_info *, bfd_vma,
33
                              unsigned short, const char *,
34
                              const enum optype [], int, int);
35
static int print_parallel_instruction (disassemble_info *, bfd_vma,
36
                                       unsigned short,
37
                                       const template *, int);
38
static int sprint_dual_address (disassemble_info *,char [],
39
                                unsigned short);
40
static int sprint_indirect_address (disassemble_info *,char [],
41
                                    unsigned short);
42
static int sprint_direct_address (disassemble_info *,char [],
43
                                  unsigned short);
44
static int sprint_mmr (disassemble_info *,char [],int);
45
static int sprint_condition (disassemble_info *,char *,unsigned short);
46
static int sprint_cc2 (disassemble_info *,char *,unsigned short);
47
 
48
int
49
print_insn_tic54x (bfd_vma memaddr, disassemble_info *info)
50
{
51
  bfd_byte opbuf[2];
52
  unsigned short opcode;
53
  int status, size;
54
  const template* tm;
55
 
56
  status = (*info->read_memory_func) (memaddr, opbuf, 2, info);
57
  if (status != 0)
58
  {
59
    (*info->memory_error_func) (status, memaddr, info);
60
    return -1;
61
  }
62
 
63
  opcode = bfd_getl16 (opbuf);
64
  tm = tic54x_get_insn (info, memaddr, opcode, &size);
65
 
66
  info->bytes_per_line = 2;
67
  info->bytes_per_chunk = 2;
68
  info->octets_per_byte = 2;
69
  info->display_endian = BFD_ENDIAN_LITTLE;
70
 
71
  if (tm->flags & FL_PAR)
72
  {
73
    if (!print_parallel_instruction (info, memaddr, opcode, tm, size))
74
      return -1;
75
  }
76
  else
77
  {
78
    if (!print_instruction (info, memaddr, opcode,
79
                            (char *) tm->name,
80
                            tm->operand_types,
81
                            size, (tm->flags & FL_EXT)))
82
      return -1;
83
  }
84
 
85
  return size * 2;
86
}
87
 
88
static int
89
has_lkaddr (unsigned short memdata, const template *tm)
90
{
91
  return (IS_LKADDR (memdata)
92
          && (OPTYPE (tm->operand_types[0]) == OP_Smem
93
              || OPTYPE (tm->operand_types[1]) == OP_Smem
94
              || OPTYPE (tm->operand_types[2]) == OP_Smem
95
              || OPTYPE (tm->operand_types[1]) == OP_Sind
96
              || OPTYPE (tm->operand_types[0]) == OP_Lmem
97
              || OPTYPE (tm->operand_types[1]) == OP_Lmem));
98
}
99
 
100
/* always returns 1 (whether an insn template was found) since we provide an
101
   "unknown instruction" template */
102
const template*
103
tic54x_get_insn (disassemble_info *info, bfd_vma addr,
104
                 unsigned short memdata, int *size)
105
{
106
  const template *tm = NULL;
107
 
108
  for (tm = tic54x_optab; tm->name; tm++)
109
  {
110
    if (tm->opcode == (memdata & tm->mask))
111
    {
112
      /* a few opcodes span two words */
113
      if (tm->flags & FL_EXT)
114
        {
115
          /* if lk addressing is used, the second half of the opcode gets
116
             pushed one word later */
117
          bfd_byte opbuf[2];
118
          bfd_vma addr2 = addr + 1 + has_lkaddr (memdata, tm);
119
          int status = (*info->read_memory_func) (addr2, opbuf, 2, info);
120
          // FIXME handle errors
121
          if (status == 0)
122
            {
123
              unsigned short data2 = bfd_getl16 (opbuf);
124
              if (tm->opcode2 == (data2 & tm->mask2))
125
                {
126
                  if (size) *size = get_insn_size (memdata, tm);
127
                  return tm;
128
                }
129
            }
130
        }
131
      else
132
        {
133
          if (size) *size = get_insn_size (memdata, tm);
134
          return tm;
135
        }
136
    }
137
  }
138
  for (tm = (template *) tic54x_paroptab; tm->name; tm++)
139
  {
140
    if (tm->opcode == (memdata & tm->mask))
141
    {
142
      if (size) *size = get_insn_size (memdata, tm);
143
      return tm;
144
    }
145
  }
146
 
147
  if (size) *size = 1;
148
  return &tic54x_unknown_opcode;
149
}
150
 
151
static int
152
get_insn_size (unsigned short memdata, const template *insn)
153
{
154
  int size;
155
 
156
  if (insn->flags & FL_PAR)
157
    {
158
      /* only non-parallel instructions support lk addressing */
159
      size = insn->words;
160
    }
161
  else
162
    {
163
      size = insn->words + has_lkaddr (memdata, insn);
164
    }
165
 
166
  return size;
167
}
168
 
169
int
170
print_instruction (info, memaddr, opcode, tm_name, tm_operands, size, ext)
171
  disassemble_info *info;
172
  bfd_vma memaddr;
173
  unsigned short opcode;
174
  const char *tm_name;
175
  const enum optype tm_operands[];
176
  int size;
177
  int ext;
178
{
179
  static int n;
180
  /* string storage for multiple operands */
181
  char operand[4][64] = { {0},{0},{0},{0}, };
182
  bfd_byte buf[2];
183
  unsigned long opcode2 = 0;
184
  unsigned long lkaddr = 0;
185
  enum optype src = OP_None;
186
  enum optype dst = OP_None;
187
  int i, shift;
188
  char *comma = "";
189
 
190
  info->fprintf_func (info->stream, "%-7s", tm_name);
191
 
192
  if (size > 1)
193
    {
194
      int status = (*info->read_memory_func) (memaddr + 1, buf, 2, info);
195
      if (status != 0)
196
        return 0;
197
      lkaddr = opcode2 = bfd_getl16 (buf);
198
      if (size > 2)
199
        {
200
          status = (*info->read_memory_func) (memaddr + 2, buf, 2, info);
201
          if (status != 0)
202
            return 0;
203
          opcode2 = bfd_getl16 (buf);
204
        }
205
    }
206
 
207
  for (i = 0; i < MAX_OPERANDS && OPTYPE (tm_operands[i]) != OP_None; i++)
208
    {
209
      char *next_comma = ",";
210
      int optional = (tm_operands[i] & OPT) != 0;
211
 
212
      switch (OPTYPE (tm_operands[i]))
213
        {
214
        case OP_Xmem:
215
          sprint_dual_address (info, operand[i], XMEM (opcode));
216
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
217
          break;
218
        case OP_Ymem:
219
          sprint_dual_address (info, operand[i], YMEM (opcode));
220
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
221
          break;
222
        case OP_Smem:
223
        case OP_Sind:
224
        case OP_Lmem:
225
          info->fprintf_func (info->stream, "%s", comma);
226
          if (INDIRECT (opcode))
227
            {
228
              if (MOD (opcode) >= 12)
229
                {
230
                  bfd_vma addr = lkaddr;
231
                  int arf = ARF (opcode);
232
                  int mod = MOD (opcode);
233
                  if (mod == 15)
234
                      info->fprintf_func (info->stream, "*(");
235
                  else
236
                      info->fprintf_func (info->stream, "*%sar%d(",
237
                                          (mod == 13 || mod == 14 ? "+" : ""),
238
                                          arf);
239
                  (*(info->print_address_func)) ((bfd_vma) addr, info);
240
                  info->fprintf_func (info->stream, ")%s",
241
                                      mod == 14 ? "%" : "");
242
                }
243
              else
244
                {
245
                  sprint_indirect_address (info, operand[i], opcode);
246
                  info->fprintf_func (info->stream, "%s", operand[i]);
247
                }
248
            }
249
          else
250
          {
251
            /* FIXME -- use labels (print_address_func) */
252
            /* in order to do this, we need to guess what DP is */
253
            sprint_direct_address (info, operand[i], opcode);
254
            info->fprintf_func (info->stream, "%s", operand[i]);
255
          }
256
          break;
257
        case OP_dmad:
258
          info->fprintf_func (info->stream, "%s", comma);
259
          (*(info->print_address_func)) ((bfd_vma) opcode2, info);
260
          break;
261
        case OP_xpmad:
262
          /* upper 7 bits of address are in the opcode */
263
          opcode2 += ((unsigned long) opcode & 0x7F) << 16;
264
          /* fall through */
265
        case OP_pmad:
266
          info->fprintf_func (info->stream, "%s", comma);
267
          (*(info->print_address_func)) ((bfd_vma) opcode2, info);
268
          break;
269
        case OP_MMRX:
270
          sprint_mmr (info, operand[i], MMRX (opcode));
271
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
272
          break;
273
        case OP_MMRY:
274
          sprint_mmr (info, operand[i], MMRY (opcode));
275
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
276
          break;
277
        case OP_MMR:
278
          sprint_mmr (info, operand[i], MMR (opcode));
279
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
280
          break;
281
        case OP_PA:
282
          sprintf (operand[i], "pa%d", (unsigned) opcode2);
283
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
284
          break;
285
        case OP_SRC:
286
          src = SRC (ext ? opcode2 : opcode) ? OP_B : OP_A;
287
          sprintf (operand[i], (src == OP_B) ? "b" : "a");
288
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
289
          break;
290
        case OP_SRC1:
291
          src = SRC1 (ext ? opcode2 : opcode) ? OP_B : OP_A;
292
          sprintf (operand[i], (src == OP_B) ? "b" : "a");
293
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
294
          break;
295
        case OP_RND:
296
          dst = DST (opcode) ? OP_B : OP_A;
297
          sprintf (operand[i], (dst == OP_B) ? "a" : "b");
298
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
299
          break;
300
        case OP_DST:
301
          dst = DST (ext ? opcode2 : opcode) ? OP_B : OP_A;
302
          if (!optional || dst != src)
303
            {
304
              sprintf (operand[i], (dst == OP_B) ? "b" : "a");
305
              info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
306
            }
307
          else
308
            next_comma = comma;
309
          break;
310
        case OP_B:
311
          sprintf (operand[i], "b");
312
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
313
          break;
314
        case OP_A:
315
          sprintf (operand[i], "a");
316
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
317
          break;
318
        case OP_ARX:
319
          sprintf (operand[i], "ar%d", (int) ARX (opcode));
320
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
321
          break;
322
        case OP_SHIFT:
323
          shift = SHIFT (ext ? opcode2 : opcode);
324
          if (!optional || shift != 0)
325
            {
326
              sprintf (operand[i], "%d", shift);
327
              info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
328
            }
329
          else
330
            next_comma = comma;
331
          break;
332
        case OP_SHFT:
333
          shift = SHFT (opcode);
334
          if (!optional || shift != 0)
335
            {
336
              sprintf (operand[i], "%d", (unsigned) shift);
337
              info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
338
            }
339
          else
340
            next_comma = comma;
341
          break;
342
        case OP_lk:
343
          sprintf (operand[i], "#%d", (int) (short) opcode2);
344
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
345
          break;
346
        case OP_T:
347
          sprintf (operand[i], "t");
348
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
349
          break;
350
        case OP_TS:
351
          sprintf (operand[i], "ts");
352
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
353
          break;
354
        case OP_k8:
355
          sprintf (operand[i], "%d", (int) ((signed char) (opcode & 0xFF)));
356
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
357
          break;
358
        case OP_16:
359
          sprintf (operand[i], "16");
360
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
361
          break;
362
        case OP_ASM:
363
          sprintf (operand[i], "asm");
364
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
365
          break;
366
        case OP_BITC:
367
          sprintf (operand[i], "%d", (int) (opcode & 0xF));
368
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
369
          break;
370
        case OP_CC:
371
          /* put all CC operands in the same operand */
372
          sprint_condition (info, operand[i], opcode);
373
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
374
          i = MAX_OPERANDS;
375
          break;
376
        case OP_CC2:
377
          sprint_cc2 (info, operand[i], opcode);
378
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
379
          break;
380
        case OP_CC3:
381
        {
382
          const char *code[] = { "eq", "lt", "gt", "neq" };
383
          sprintf (operand[i], code[CC3 (opcode)]);
384
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
385
          break;
386
        }
387
        case OP_123:
388
          {
389
            int code = (opcode >> 8) & 0x3;
390
            sprintf (operand[i], "%d", (code == 0) ? 1 : (code == 2) ? 2 : 3);
391
            info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
392
            break;
393
          }
394
        case OP_k5:
395
          sprintf (operand[i], "#%d",
396
                   (int) (((signed char) opcode & 0x1F) << 3) >> 3);
397
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
398
          break;
399
        case OP_k8u:
400
          sprintf (operand[i], "#%d", (unsigned) (opcode & 0xFF));
401
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
402
          break;
403
        case OP_k3:
404
          sprintf (operand[i], "#%d", (int) (opcode & 0x7));
405
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
406
          break;
407
        case OP_lku:
408
          sprintf (operand[i], "#%d", (unsigned) opcode2);
409
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
410
          break;
411
        case OP_N:
412
          n = (opcode >> 9) & 0x1;
413
          sprintf (operand[i], "st%d", n);
414
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
415
          break;
416
        case OP_SBIT:
417
        {
418
          const char *status0[] = {
419
            "0", "1", "2", "3", "4", "5", "6", "7", "8",
420
            "ovb", "ova", "c", "tc", "13", "14", "15"
421
          };
422
          const char *status1[] = {
423
            "0", "1", "2", "3", "4",
424
            "cmpt", "frct", "c16", "sxm", "ovm", "10",
425
            "intm", "hm", "xf", "cpl", "braf"
426
          };
427
          sprintf (operand[i], "%s",
428
                   n ? status1[SBIT (opcode)] : status0[SBIT (opcode)]);
429
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
430
          break;
431
        }
432
        case OP_12:
433
          sprintf (operand[i], "%d", (int) ((opcode >> 9) & 1) + 1);
434
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
435
          break;
436
        case OP_TRN:
437
          sprintf (operand[i], "trn");
438
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
439
          break;
440
        case OP_DP:
441
          sprintf (operand[i], "dp");
442
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
443
          break;
444
        case OP_k9:
445
          /* FIXME-- this is DP, print the original address? */
446
          sprintf (operand[i], "#%d", (int) (opcode & 0x1FF));
447
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
448
          break;
449
        case OP_ARP:
450
          sprintf (operand[i], "arp");
451
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
452
          break;
453
        case OP_031:
454
          sprintf (operand[i], "%d", (int) (opcode & 0x1F));
455
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
456
          break;
457
        default:
458
          sprintf (operand[i], "??? (0x%x)", tm_operands[i]);
459
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
460
          break;
461
        }
462
      comma = next_comma;
463
    }
464
  return 1;
465
}
466
 
467
static int
468
print_parallel_instruction (info, memaddr, opcode, ptm, size)
469
  disassemble_info *info;
470
  bfd_vma memaddr;
471
  unsigned short opcode;
472
  const template *ptm;
473
  int size;
474
{
475
  print_instruction (info, memaddr, opcode,
476
                     ptm->name, ptm->operand_types, size, 0);
477
  info->fprintf_func (info->stream, " || ");
478
  return print_instruction (info, memaddr, opcode,
479
                            ptm->parname, ptm->paroperand_types, size, 0);
480
}
481
 
482
static int
483
sprint_dual_address (info, buf, code)
484
  disassemble_info *info ATTRIBUTE_UNUSED;
485
  char buf[];
486
  unsigned short code;
487
{
488
  const char *formats[] = {
489
    "*ar%d",
490
    "*ar%d-",
491
    "*ar%d+",
492
    "*ar%d+0%%",
493
  };
494
  return sprintf (buf, formats[XMOD (code)], XARX (code));
495
}
496
 
497
static int
498
sprint_indirect_address (info, buf, opcode)
499
  disassemble_info *info ATTRIBUTE_UNUSED;
500
  char buf[];
501
  unsigned short opcode;
502
{
503
  const char *formats[] = {
504
    "*ar%d",
505
    "*ar%d-",
506
    "*ar%d+",
507
    "*+ar%d",
508
    "*ar%d-0B",
509
    "*ar%d-0",
510
    "*ar%d+0",
511
    "*ar%d+0B",
512
    "*ar%d-%%",
513
    "*ar%d-0%%",
514
    "*ar%d+%%",
515
    "*ar%d+0%%",
516
  };
517
  return sprintf (buf, formats[MOD (opcode)], ARF (opcode));
518
}
519
 
520
static int
521
sprint_direct_address (info, buf, opcode)
522
  disassemble_info *info ATTRIBUTE_UNUSED;
523
  char buf[];
524
  unsigned short opcode;
525
{
526
  /* FIXME -- look up relocation if available */
527
  return sprintf (buf, "DP+0x%02x", (int) (opcode & 0x7F));
528
}
529
 
530
static int
531
sprint_mmr (info, buf, mmr)
532
  disassemble_info *info ATTRIBUTE_UNUSED;
533
  char buf[];
534
  int mmr;
535
{
536
  symbol *reg = (symbol *) mmregs;
537
  while (reg->name != NULL)
538
    {
539
      if (mmr == reg->value)
540
        {
541
          sprintf (buf, "%s", (reg + 1)->name);
542
          return 1;
543
        }
544
      ++reg;
545
    }
546
  sprintf (buf, "MMR(%d)", mmr); /* FIXME -- different targets.  */
547
  return 0;
548
}
549
 
550
static int
551
sprint_cc2 (info, buf, opcode)
552
  disassemble_info *info ATTRIBUTE_UNUSED;
553
  char *buf;
554
  unsigned short opcode;
555
{
556
  const char *cc2[] = {
557
    "??", "??", "ageq", "alt", "aneq", "aeq", "agt", "aleq",
558
    "??", "??", "bgeq", "blt", "bneq", "beq", "bgt", "bleq",
559
  };
560
  return sprintf (buf, "%s", cc2[opcode & 0xF]);
561
}
562
 
563
static int
564
sprint_condition (info, buf, opcode)
565
  disassemble_info *info ATTRIBUTE_UNUSED;
566
  char *buf;
567
  unsigned short opcode;
568
{
569
  char *start = buf;
570
  const char *cmp[] = {
571
      "??", "??", "geq", "lt", "neq", "eq", "gt", "leq"
572
  };
573
  if (opcode & 0x40)
574
    {
575
      char acc = (opcode & 0x8) ? 'b' : 'a';
576
      if (opcode & 0x7)
577
          buf += sprintf (buf, "%c%s%s", acc, cmp[(opcode & 0x7)],
578
                          (opcode & 0x20) ? ", " : "");
579
      if (opcode & 0x20)
580
          buf += sprintf (buf, "%c%s", acc, (opcode & 0x10) ? "ov" : "nov");
581
    }
582
  else if (opcode & 0x3F)
583
    {
584
      if (opcode & 0x30)
585
        buf += sprintf (buf, "%s%s",
586
                        ((opcode & 0x30) == 0x30) ? "tc" : "ntc",
587
                        (opcode & 0x0F) ? ", " : "");
588
      if (opcode & 0x0C)
589
        buf += sprintf (buf, "%s%s",
590
                        ((opcode & 0x0C) == 0x0C) ? "c" : "nc",
591
                        (opcode & 0x03) ? ", " : "");
592
      if (opcode & 0x03)
593
        buf += sprintf (buf, "%s",
594
                        ((opcode & 0x03) == 0x03) ? "bio" : "nbio");
595
    }
596
  else
597
    buf += sprintf (buf, "unc");
598
 
599
  return buf - start;
600
}

powered by: WebSVN 2.1.0

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