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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 18 khays
/* Disassembly routines for TMS320C54X architecture
2
   Copyright 1999, 2000, 2001, 2005, 2007, 2009 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 insn_template *);
31
static int get_insn_size (unsigned short, const insn_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 insn_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 insn_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 insn_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 insn_template*
103
tic54x_get_insn (disassemble_info *info, bfd_vma addr,
104
                 unsigned short memdata, int *size)
105
{
106
  const insn_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 = (insn_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 insn_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
 
384
          /* Do not use sprintf with only two parameters as a
385
             compiler warning could be generated in such conditions.  */
386
          sprintf (operand[i], "%s", code[CC3 (opcode)]);
387
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
388
          break;
389
        }
390
        case OP_123:
391
          {
392
            int code = (opcode >> 8) & 0x3;
393
            sprintf (operand[i], "%d", (code == 0) ? 1 : (code == 2) ? 2 : 3);
394
            info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
395
            break;
396
          }
397
        case OP_k5:
398
          sprintf (operand[i], "#%d",
399
                   (int) (((signed char) opcode & 0x1F) << 3) >> 3);
400
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
401
          break;
402
        case OP_k8u:
403
          sprintf (operand[i], "#%d", (unsigned) (opcode & 0xFF));
404
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
405
          break;
406
        case OP_k3:
407
          sprintf (operand[i], "#%d", (int) (opcode & 0x7));
408
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
409
          break;
410
        case OP_lku:
411
          sprintf (operand[i], "#%d", (unsigned) opcode2);
412
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
413
          break;
414
        case OP_N:
415
          n = (opcode >> 9) & 0x1;
416
          sprintf (operand[i], "st%d", n);
417
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
418
          break;
419
        case OP_SBIT:
420
        {
421
          const char *status0[] = {
422
            "0", "1", "2", "3", "4", "5", "6", "7", "8",
423
            "ovb", "ova", "c", "tc", "13", "14", "15"
424
          };
425
          const char *status1[] = {
426
            "0", "1", "2", "3", "4",
427
            "cmpt", "frct", "c16", "sxm", "ovm", "10",
428
            "intm", "hm", "xf", "cpl", "braf"
429
          };
430
          sprintf (operand[i], "%s",
431
                   n ? status1[SBIT (opcode)] : status0[SBIT (opcode)]);
432
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
433
          break;
434
        }
435
        case OP_12:
436
          sprintf (operand[i], "%d", (int) ((opcode >> 9) & 1) + 1);
437
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
438
          break;
439
        case OP_TRN:
440
          sprintf (operand[i], "trn");
441
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
442
          break;
443
        case OP_DP:
444
          sprintf (operand[i], "dp");
445
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
446
          break;
447
        case OP_k9:
448
          /* FIXME-- this is DP, print the original address? */
449
          sprintf (operand[i], "#%d", (int) (opcode & 0x1FF));
450
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
451
          break;
452
        case OP_ARP:
453
          sprintf (operand[i], "arp");
454
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
455
          break;
456
        case OP_031:
457
          sprintf (operand[i], "%d", (int) (opcode & 0x1F));
458
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
459
          break;
460
        default:
461
          sprintf (operand[i], "??? (0x%x)", tm_operands[i]);
462
          info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
463
          break;
464
        }
465
      comma = next_comma;
466
    }
467
  return 1;
468
}
469
 
470
static int
471
print_parallel_instruction (info, memaddr, opcode, ptm, size)
472
  disassemble_info *info;
473
  bfd_vma memaddr;
474
  unsigned short opcode;
475
  const insn_template *ptm;
476
  int size;
477
{
478
  print_instruction (info, memaddr, opcode,
479
                     ptm->name, ptm->operand_types, size, 0);
480
  info->fprintf_func (info->stream, " || ");
481
  return print_instruction (info, memaddr, opcode,
482
                            ptm->parname, ptm->paroperand_types, size, 0);
483
}
484
 
485
static int
486
sprint_dual_address (info, buf, code)
487
  disassemble_info *info ATTRIBUTE_UNUSED;
488
  char buf[];
489
  unsigned short code;
490
{
491
  const char *formats[] = {
492
    "*ar%d",
493
    "*ar%d-",
494
    "*ar%d+",
495
    "*ar%d+0%%",
496
  };
497
  return sprintf (buf, formats[XMOD (code)], XARX (code));
498
}
499
 
500
static int
501
sprint_indirect_address (info, buf, opcode)
502
  disassemble_info *info ATTRIBUTE_UNUSED;
503
  char buf[];
504
  unsigned short opcode;
505
{
506
  const char *formats[] = {
507
    "*ar%d",
508
    "*ar%d-",
509
    "*ar%d+",
510
    "*+ar%d",
511
    "*ar%d-0B",
512
    "*ar%d-0",
513
    "*ar%d+0",
514
    "*ar%d+0B",
515
    "*ar%d-%%",
516
    "*ar%d-0%%",
517
    "*ar%d+%%",
518
    "*ar%d+0%%",
519
  };
520
  return sprintf (buf, formats[MOD (opcode)], ARF (opcode));
521
}
522
 
523
static int
524
sprint_direct_address (info, buf, opcode)
525
  disassemble_info *info ATTRIBUTE_UNUSED;
526
  char buf[];
527
  unsigned short opcode;
528
{
529
  /* FIXME -- look up relocation if available */
530
  return sprintf (buf, "DP+0x%02x", (int) (opcode & 0x7F));
531
}
532
 
533
static int
534
sprint_mmr (info, buf, mmr)
535
  disassemble_info *info ATTRIBUTE_UNUSED;
536
  char buf[];
537
  int mmr;
538
{
539
  symbol *reg = (symbol *) mmregs;
540
  while (reg->name != NULL)
541
    {
542
      if (mmr == reg->value)
543
        {
544
          sprintf (buf, "%s", (reg + 1)->name);
545
          return 1;
546
        }
547
      ++reg;
548
    }
549
  sprintf (buf, "MMR(%d)", mmr); /* FIXME -- different targets.  */
550
  return 0;
551
}
552
 
553
static int
554
sprint_cc2 (info, buf, opcode)
555
  disassemble_info *info ATTRIBUTE_UNUSED;
556
  char *buf;
557
  unsigned short opcode;
558
{
559
  const char *cc2[] = {
560
    "??", "??", "ageq", "alt", "aneq", "aeq", "agt", "aleq",
561
    "??", "??", "bgeq", "blt", "bneq", "beq", "bgt", "bleq",
562
  };
563
  return sprintf (buf, "%s", cc2[opcode & 0xF]);
564
}
565
 
566
static int
567
sprint_condition (info, buf, opcode)
568
  disassemble_info *info ATTRIBUTE_UNUSED;
569
  char *buf;
570
  unsigned short opcode;
571
{
572
  char *start = buf;
573
  const char *cmp[] = {
574
      "??", "??", "geq", "lt", "neq", "eq", "gt", "leq"
575
  };
576
  if (opcode & 0x40)
577
    {
578
      char acc = (opcode & 0x8) ? 'b' : 'a';
579
      if (opcode & 0x7)
580
          buf += sprintf (buf, "%c%s%s", acc, cmp[(opcode & 0x7)],
581
                          (opcode & 0x20) ? ", " : "");
582
      if (opcode & 0x20)
583
          buf += sprintf (buf, "%c%s", acc, (opcode & 0x10) ? "ov" : "nov");
584
    }
585
  else if (opcode & 0x3F)
586
    {
587
      if (opcode & 0x30)
588
        buf += sprintf (buf, "%s%s",
589
                        ((opcode & 0x30) == 0x30) ? "tc" : "ntc",
590
                        (opcode & 0x0F) ? ", " : "");
591
      if (opcode & 0x0C)
592
        buf += sprintf (buf, "%s%s",
593
                        ((opcode & 0x0C) == 0x0C) ? "c" : "nc",
594
                        (opcode & 0x03) ? ", " : "");
595
      if (opcode & 0x03)
596
        buf += sprintf (buf, "%s",
597
                        ((opcode & 0x03) == 0x03) ? "bio" : "nbio");
598
    }
599
  else
600
    buf += sprintf (buf, "unc");
601
 
602
  return buf - start;
603
}

powered by: WebSVN 2.1.0

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