source: branches/libc-0.6/src/binutils/opcodes/tic54x-dis.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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