xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/tic54x-dis.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* Disassembly routines for TMS320C54X architecture
2*e992f068Schristos    Copyright (C) 1999-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Contributed by Timothy Wall (twall@cygnus.com)
475fd0b74Schristos 
575fd0b74Schristos    This file is part of the GNU opcodes library.
675fd0b74Schristos 
775fd0b74Schristos    This library is free software; you can redistribute it and/or modify
875fd0b74Schristos    it under the terms of the GNU General Public License as published by
975fd0b74Schristos    the Free Software Foundation; either version 3, or (at your option)
1075fd0b74Schristos    any later version.
1175fd0b74Schristos 
1275fd0b74Schristos    It is distributed in the hope that it will be useful, but WITHOUT
1375fd0b74Schristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1475fd0b74Schristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1575fd0b74Schristos    License for more details.
1675fd0b74Schristos 
1775fd0b74Schristos    You should have received a copy of the GNU General Public License
1875fd0b74Schristos    along with this file; see the file COPYING.  If not, write to the
1975fd0b74Schristos    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
2075fd0b74Schristos    MA 02110-1301, USA.  */
2175fd0b74Schristos 
2275fd0b74Schristos #include "sysdep.h"
2375fd0b74Schristos #include <errno.h>
2475fd0b74Schristos #include <math.h>
2575fd0b74Schristos #include <stdlib.h>
26ede78133Schristos #include "disassemble.h"
2775fd0b74Schristos #include "opcode/tic54x.h"
2875fd0b74Schristos #include "coff/tic54x.h"
2975fd0b74Schristos 
3075fd0b74Schristos static int has_lkaddr (unsigned short, const insn_template *);
3175fd0b74Schristos static int get_insn_size (unsigned short, const insn_template *);
3275fd0b74Schristos static int print_instruction (disassemble_info *, bfd_vma,
3375fd0b74Schristos                               unsigned short, const char *,
3475fd0b74Schristos                               const enum optype [], int, int);
3575fd0b74Schristos static int print_parallel_instruction (disassemble_info *, bfd_vma,
3675fd0b74Schristos                                        unsigned short,
3775fd0b74Schristos                                        const insn_template *, int);
3875fd0b74Schristos static int sprint_dual_address (disassemble_info *,char [],
3975fd0b74Schristos                                 unsigned short);
4075fd0b74Schristos static int sprint_indirect_address (disassemble_info *,char [],
4175fd0b74Schristos                                     unsigned short);
4275fd0b74Schristos static int sprint_direct_address (disassemble_info *,char [],
4375fd0b74Schristos                                   unsigned short);
4475fd0b74Schristos static int sprint_mmr (disassemble_info *,char [],int);
4575fd0b74Schristos static int sprint_condition (disassemble_info *,char *,unsigned short);
4675fd0b74Schristos static int sprint_cc2 (disassemble_info *,char *,unsigned short);
4775fd0b74Schristos 
4875fd0b74Schristos int
print_insn_tic54x(bfd_vma memaddr,disassemble_info * info)4975fd0b74Schristos print_insn_tic54x (bfd_vma memaddr, disassemble_info *info)
5075fd0b74Schristos {
5175fd0b74Schristos   bfd_byte opbuf[2];
5275fd0b74Schristos   unsigned short opcode;
5375fd0b74Schristos   int status, size;
5475fd0b74Schristos   const insn_template* tm;
5575fd0b74Schristos 
5675fd0b74Schristos   status = (*info->read_memory_func) (memaddr, opbuf, 2, info);
5775fd0b74Schristos   if (status != 0)
5875fd0b74Schristos   {
5975fd0b74Schristos     (*info->memory_error_func) (status, memaddr, info);
6075fd0b74Schristos     return -1;
6175fd0b74Schristos   }
6275fd0b74Schristos 
6375fd0b74Schristos   opcode = bfd_getl16 (opbuf);
6475fd0b74Schristos   tm = tic54x_get_insn (info, memaddr, opcode, &size);
6575fd0b74Schristos 
6675fd0b74Schristos   info->bytes_per_line = 2;
6775fd0b74Schristos   info->bytes_per_chunk = 2;
6875fd0b74Schristos   info->octets_per_byte = 2;
6975fd0b74Schristos   info->display_endian = BFD_ENDIAN_LITTLE;
7075fd0b74Schristos 
7175fd0b74Schristos   if (tm->flags & FL_PAR)
7275fd0b74Schristos   {
7375fd0b74Schristos     if (!print_parallel_instruction (info, memaddr, opcode, tm, size))
7475fd0b74Schristos       return -1;
7575fd0b74Schristos   }
7675fd0b74Schristos   else
7775fd0b74Schristos   {
7875fd0b74Schristos     if (!print_instruction (info, memaddr, opcode,
7975fd0b74Schristos                             (char *) tm->name,
8075fd0b74Schristos                             tm->operand_types,
8175fd0b74Schristos                             size, (tm->flags & FL_EXT)))
8275fd0b74Schristos       return -1;
8375fd0b74Schristos   }
8475fd0b74Schristos 
8575fd0b74Schristos   return size * 2;
8675fd0b74Schristos }
8775fd0b74Schristos 
8875fd0b74Schristos static int
has_lkaddr(unsigned short memdata,const insn_template * tm)8975fd0b74Schristos has_lkaddr (unsigned short memdata, const insn_template *tm)
9075fd0b74Schristos {
9175fd0b74Schristos   return (IS_LKADDR (memdata)
9275fd0b74Schristos 	  && (OPTYPE (tm->operand_types[0]) == OP_Smem
9375fd0b74Schristos 	      || OPTYPE (tm->operand_types[1]) == OP_Smem
9475fd0b74Schristos 	      || OPTYPE (tm->operand_types[2]) == OP_Smem
9575fd0b74Schristos 	      || OPTYPE (tm->operand_types[1]) == OP_Sind
9675fd0b74Schristos               || OPTYPE (tm->operand_types[0]) == OP_Lmem
9775fd0b74Schristos               || OPTYPE (tm->operand_types[1]) == OP_Lmem));
9875fd0b74Schristos }
9975fd0b74Schristos 
10075fd0b74Schristos /* always returns 1 (whether an insn template was found) since we provide an
10175fd0b74Schristos    "unknown instruction" template */
10275fd0b74Schristos const insn_template*
tic54x_get_insn(disassemble_info * info,bfd_vma addr,unsigned short memdata,int * size)10375fd0b74Schristos tic54x_get_insn (disassemble_info *info, bfd_vma addr,
10475fd0b74Schristos                  unsigned short memdata, int *size)
10575fd0b74Schristos {
10675fd0b74Schristos   const insn_template *tm = NULL;
10775fd0b74Schristos 
10875fd0b74Schristos   for (tm = tic54x_optab; tm->name; tm++)
10975fd0b74Schristos   {
11075fd0b74Schristos     if (tm->opcode == (memdata & tm->mask))
11175fd0b74Schristos     {
11275fd0b74Schristos       /* a few opcodes span two words */
11375fd0b74Schristos       if (tm->flags & FL_EXT)
11475fd0b74Schristos         {
11575fd0b74Schristos           /* if lk addressing is used, the second half of the opcode gets
11675fd0b74Schristos              pushed one word later */
11775fd0b74Schristos           bfd_byte opbuf[2];
11875fd0b74Schristos           bfd_vma addr2 = addr + 1 + has_lkaddr (memdata, tm);
11975fd0b74Schristos           int status = (*info->read_memory_func) (addr2, opbuf, 2, info);
120*e992f068Schristos           /* FIXME handle errors.  */
12175fd0b74Schristos           if (status == 0)
12275fd0b74Schristos             {
12375fd0b74Schristos               unsigned short data2 = bfd_getl16 (opbuf);
12475fd0b74Schristos               if (tm->opcode2 == (data2 & tm->mask2))
12575fd0b74Schristos                 {
12675fd0b74Schristos                   if (size) *size = get_insn_size (memdata, tm);
12775fd0b74Schristos                   return tm;
12875fd0b74Schristos                 }
12975fd0b74Schristos             }
13075fd0b74Schristos         }
13175fd0b74Schristos       else
13275fd0b74Schristos         {
13375fd0b74Schristos           if (size) *size = get_insn_size (memdata, tm);
13475fd0b74Schristos           return tm;
13575fd0b74Schristos         }
13675fd0b74Schristos     }
13775fd0b74Schristos   }
13875fd0b74Schristos   for (tm = (insn_template *) tic54x_paroptab; tm->name; tm++)
13975fd0b74Schristos   {
14075fd0b74Schristos     if (tm->opcode == (memdata & tm->mask))
14175fd0b74Schristos     {
14275fd0b74Schristos       if (size) *size = get_insn_size (memdata, tm);
14375fd0b74Schristos       return tm;
14475fd0b74Schristos     }
14575fd0b74Schristos   }
14675fd0b74Schristos 
14775fd0b74Schristos   if (size) *size = 1;
14875fd0b74Schristos   return &tic54x_unknown_opcode;
14975fd0b74Schristos }
15075fd0b74Schristos 
15175fd0b74Schristos static int
get_insn_size(unsigned short memdata,const insn_template * insn)15275fd0b74Schristos get_insn_size (unsigned short memdata, const insn_template *insn)
15375fd0b74Schristos {
15475fd0b74Schristos   int size;
15575fd0b74Schristos 
15675fd0b74Schristos   if (insn->flags & FL_PAR)
15775fd0b74Schristos     {
15875fd0b74Schristos       /* only non-parallel instructions support lk addressing */
15975fd0b74Schristos       size = insn->words;
16075fd0b74Schristos     }
16175fd0b74Schristos   else
16275fd0b74Schristos     {
16375fd0b74Schristos       size = insn->words + has_lkaddr (memdata, insn);
16475fd0b74Schristos     }
16575fd0b74Schristos 
16675fd0b74Schristos   return size;
16775fd0b74Schristos }
16875fd0b74Schristos 
16975fd0b74Schristos int
print_instruction(disassemble_info * info,bfd_vma memaddr,unsigned short opcode,const char * tm_name,const enum optype tm_operands[],int size,int ext)17075fd0b74Schristos print_instruction (disassemble_info *info,
17175fd0b74Schristos 		   bfd_vma memaddr,
17275fd0b74Schristos 		   unsigned short opcode,
17375fd0b74Schristos 		   const char *tm_name,
17475fd0b74Schristos 		   const enum optype tm_operands[],
17575fd0b74Schristos 		   int size,
17675fd0b74Schristos 		   int ext)
17775fd0b74Schristos {
17875fd0b74Schristos   static int n;
17975fd0b74Schristos   /* string storage for multiple operands */
18075fd0b74Schristos   char operand[4][64] = { {0},{0},{0},{0}, };
18175fd0b74Schristos   bfd_byte buf[2];
18275fd0b74Schristos   unsigned long opcode2 = 0;
18375fd0b74Schristos   unsigned long lkaddr = 0;
18475fd0b74Schristos   enum optype src = OP_None;
18575fd0b74Schristos   enum optype dst = OP_None;
18675fd0b74Schristos   int i, shift;
18775fd0b74Schristos   char *comma = "";
18875fd0b74Schristos 
18975fd0b74Schristos   info->fprintf_func (info->stream, "%-7s", tm_name);
19075fd0b74Schristos 
19175fd0b74Schristos   if (size > 1)
19275fd0b74Schristos     {
19375fd0b74Schristos       int status = (*info->read_memory_func) (memaddr + 1, buf, 2, info);
19475fd0b74Schristos       if (status != 0)
19575fd0b74Schristos         return 0;
19675fd0b74Schristos       lkaddr = opcode2 = bfd_getl16 (buf);
19775fd0b74Schristos       if (size > 2)
19875fd0b74Schristos         {
19975fd0b74Schristos           status = (*info->read_memory_func) (memaddr + 2, buf, 2, info);
20075fd0b74Schristos           if (status != 0)
20175fd0b74Schristos             return 0;
20275fd0b74Schristos           opcode2 = bfd_getl16 (buf);
20375fd0b74Schristos         }
20475fd0b74Schristos     }
20575fd0b74Schristos 
20675fd0b74Schristos   for (i = 0; i < MAX_OPERANDS && OPTYPE (tm_operands[i]) != OP_None; i++)
20775fd0b74Schristos     {
20875fd0b74Schristos       char *next_comma = ",";
20975fd0b74Schristos       int optional = (tm_operands[i] & OPT) != 0;
21075fd0b74Schristos 
21175fd0b74Schristos       switch (OPTYPE (tm_operands[i]))
21275fd0b74Schristos         {
21375fd0b74Schristos         case OP_Xmem:
21475fd0b74Schristos           sprint_dual_address (info, operand[i], XMEM (opcode));
21575fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
21675fd0b74Schristos           break;
21775fd0b74Schristos         case OP_Ymem:
21875fd0b74Schristos           sprint_dual_address (info, operand[i], YMEM (opcode));
21975fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
22075fd0b74Schristos           break;
22175fd0b74Schristos         case OP_Smem:
22275fd0b74Schristos         case OP_Sind:
22375fd0b74Schristos         case OP_Lmem:
22475fd0b74Schristos           info->fprintf_func (info->stream, "%s", comma);
22575fd0b74Schristos           if (INDIRECT (opcode))
22675fd0b74Schristos             {
22775fd0b74Schristos               if (MOD (opcode) >= 12)
22875fd0b74Schristos                 {
22975fd0b74Schristos                   bfd_vma addr = lkaddr;
23075fd0b74Schristos                   int arf = ARF (opcode);
23175fd0b74Schristos                   int mod = MOD (opcode);
23275fd0b74Schristos                   if (mod == 15)
23375fd0b74Schristos                       info->fprintf_func (info->stream, "*(");
23475fd0b74Schristos                   else
23575fd0b74Schristos                       info->fprintf_func (info->stream, "*%sar%d(",
23675fd0b74Schristos                                           (mod == 13 || mod == 14 ? "+" : ""),
23775fd0b74Schristos                                           arf);
23875fd0b74Schristos                   (*(info->print_address_func)) ((bfd_vma) addr, info);
23975fd0b74Schristos                   info->fprintf_func (info->stream, ")%s",
24075fd0b74Schristos                                       mod == 14 ? "%" : "");
24175fd0b74Schristos                 }
24275fd0b74Schristos               else
24375fd0b74Schristos                 {
24475fd0b74Schristos                   sprint_indirect_address (info, operand[i], opcode);
24575fd0b74Schristos                   info->fprintf_func (info->stream, "%s", operand[i]);
24675fd0b74Schristos                 }
24775fd0b74Schristos             }
24875fd0b74Schristos           else
24975fd0b74Schristos           {
25075fd0b74Schristos             /* FIXME -- use labels (print_address_func) */
25175fd0b74Schristos             /* in order to do this, we need to guess what DP is */
25275fd0b74Schristos             sprint_direct_address (info, operand[i], opcode);
25375fd0b74Schristos             info->fprintf_func (info->stream, "%s", operand[i]);
25475fd0b74Schristos           }
25575fd0b74Schristos           break;
25675fd0b74Schristos         case OP_dmad:
25775fd0b74Schristos           info->fprintf_func (info->stream, "%s", comma);
25875fd0b74Schristos           (*(info->print_address_func)) ((bfd_vma) opcode2, info);
25975fd0b74Schristos           break;
26075fd0b74Schristos         case OP_xpmad:
26175fd0b74Schristos           /* upper 7 bits of address are in the opcode */
26275fd0b74Schristos           opcode2 += ((unsigned long) opcode & 0x7F) << 16;
26375fd0b74Schristos           /* fall through */
26475fd0b74Schristos         case OP_pmad:
26575fd0b74Schristos           info->fprintf_func (info->stream, "%s", comma);
26675fd0b74Schristos           (*(info->print_address_func)) ((bfd_vma) opcode2, info);
26775fd0b74Schristos           break;
26875fd0b74Schristos         case OP_MMRX:
26975fd0b74Schristos           sprint_mmr (info, operand[i], MMRX (opcode));
27075fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
27175fd0b74Schristos           break;
27275fd0b74Schristos         case OP_MMRY:
27375fd0b74Schristos           sprint_mmr (info, operand[i], MMRY (opcode));
27475fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
27575fd0b74Schristos           break;
27675fd0b74Schristos         case OP_MMR:
27775fd0b74Schristos           sprint_mmr (info, operand[i], MMR (opcode));
27875fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
27975fd0b74Schristos           break;
28075fd0b74Schristos         case OP_PA:
28175fd0b74Schristos           sprintf (operand[i], "pa%d", (unsigned) opcode2);
28275fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
28375fd0b74Schristos           break;
28475fd0b74Schristos         case OP_SRC:
28575fd0b74Schristos           src = SRC (ext ? opcode2 : opcode) ? OP_B : OP_A;
28675fd0b74Schristos           sprintf (operand[i], (src == OP_B) ? "b" : "a");
28775fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
28875fd0b74Schristos           break;
28975fd0b74Schristos         case OP_SRC1:
29075fd0b74Schristos           src = SRC1 (ext ? opcode2 : opcode) ? OP_B : OP_A;
29175fd0b74Schristos           sprintf (operand[i], (src == OP_B) ? "b" : "a");
29275fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
29375fd0b74Schristos           break;
29475fd0b74Schristos         case OP_RND:
29575fd0b74Schristos           dst = DST (opcode) ? OP_B : OP_A;
29675fd0b74Schristos           sprintf (operand[i], (dst == OP_B) ? "a" : "b");
29775fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
29875fd0b74Schristos           break;
29975fd0b74Schristos         case OP_DST:
30075fd0b74Schristos           dst = DST (ext ? opcode2 : opcode) ? OP_B : OP_A;
30175fd0b74Schristos           if (!optional || dst != src)
30275fd0b74Schristos             {
30375fd0b74Schristos               sprintf (operand[i], (dst == OP_B) ? "b" : "a");
30475fd0b74Schristos               info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
30575fd0b74Schristos             }
30675fd0b74Schristos           else
30775fd0b74Schristos             next_comma = comma;
30875fd0b74Schristos           break;
30975fd0b74Schristos         case OP_B:
31075fd0b74Schristos           sprintf (operand[i], "b");
31175fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
31275fd0b74Schristos           break;
31375fd0b74Schristos         case OP_A:
31475fd0b74Schristos           sprintf (operand[i], "a");
31575fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
31675fd0b74Schristos           break;
31775fd0b74Schristos         case OP_ARX:
31875fd0b74Schristos           sprintf (operand[i], "ar%d", (int) ARX (opcode));
31975fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
32075fd0b74Schristos           break;
32175fd0b74Schristos         case OP_SHIFT:
32275fd0b74Schristos           shift = SHIFT (ext ? opcode2 : opcode);
32375fd0b74Schristos           if (!optional || shift != 0)
32475fd0b74Schristos             {
32575fd0b74Schristos               sprintf (operand[i], "%d", shift);
32675fd0b74Schristos               info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
32775fd0b74Schristos             }
32875fd0b74Schristos           else
32975fd0b74Schristos             next_comma = comma;
33075fd0b74Schristos           break;
33175fd0b74Schristos         case OP_SHFT:
33275fd0b74Schristos           shift = SHFT (opcode);
33375fd0b74Schristos           if (!optional || shift != 0)
33475fd0b74Schristos             {
33575fd0b74Schristos               sprintf (operand[i], "%d", (unsigned) shift);
33675fd0b74Schristos               info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
33775fd0b74Schristos             }
33875fd0b74Schristos           else
33975fd0b74Schristos             next_comma = comma;
34075fd0b74Schristos           break;
34175fd0b74Schristos         case OP_lk:
34275fd0b74Schristos           sprintf (operand[i], "#%d", (int) (short) opcode2);
34375fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
34475fd0b74Schristos           break;
34575fd0b74Schristos         case OP_T:
34675fd0b74Schristos           sprintf (operand[i], "t");
34775fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
34875fd0b74Schristos           break;
34975fd0b74Schristos         case OP_TS:
35075fd0b74Schristos           sprintf (operand[i], "ts");
35175fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
35275fd0b74Schristos           break;
35375fd0b74Schristos         case OP_k8:
35475fd0b74Schristos           sprintf (operand[i], "%d", (int) ((signed char) (opcode & 0xFF)));
35575fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
35675fd0b74Schristos           break;
35775fd0b74Schristos         case OP_16:
35875fd0b74Schristos           sprintf (operand[i], "16");
35975fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
36075fd0b74Schristos           break;
36175fd0b74Schristos         case OP_ASM:
36275fd0b74Schristos           sprintf (operand[i], "asm");
36375fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
36475fd0b74Schristos           break;
36575fd0b74Schristos         case OP_BITC:
36675fd0b74Schristos           sprintf (operand[i], "%d", (int) (opcode & 0xF));
36775fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
36875fd0b74Schristos           break;
36975fd0b74Schristos         case OP_CC:
37075fd0b74Schristos           /* put all CC operands in the same operand */
37175fd0b74Schristos           sprint_condition (info, operand[i], opcode);
37275fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
37375fd0b74Schristos           i = MAX_OPERANDS;
37475fd0b74Schristos           break;
37575fd0b74Schristos         case OP_CC2:
37675fd0b74Schristos           sprint_cc2 (info, operand[i], opcode);
37775fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
37875fd0b74Schristos           break;
37975fd0b74Schristos         case OP_CC3:
38075fd0b74Schristos         {
38175fd0b74Schristos           const char *code[] = { "eq", "lt", "gt", "neq" };
38275fd0b74Schristos 
38375fd0b74Schristos 	  /* Do not use sprintf with only two parameters as a
38475fd0b74Schristos 	     compiler warning could be generated in such conditions.  */
38575fd0b74Schristos 	  sprintf (operand[i], "%s", code[CC3 (opcode)]);
38675fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
38775fd0b74Schristos           break;
38875fd0b74Schristos         }
38975fd0b74Schristos         case OP_123:
39075fd0b74Schristos           {
39175fd0b74Schristos             int code = (opcode >> 8) & 0x3;
39275fd0b74Schristos             sprintf (operand[i], "%d", (code == 0) ? 1 : (code == 2) ? 2 : 3);
39375fd0b74Schristos             info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
39475fd0b74Schristos             break;
39575fd0b74Schristos           }
39675fd0b74Schristos         case OP_k5:
397012573ebSchristos           sprintf (operand[i], "#%d", ((opcode & 0x1F) ^ 0x10) - 0x10);
39875fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
39975fd0b74Schristos           break;
40075fd0b74Schristos         case OP_k8u:
40175fd0b74Schristos           sprintf (operand[i], "#%d", (unsigned) (opcode & 0xFF));
40275fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
40375fd0b74Schristos           break;
40475fd0b74Schristos         case OP_k3:
40575fd0b74Schristos           sprintf (operand[i], "#%d", (int) (opcode & 0x7));
40675fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
40775fd0b74Schristos           break;
40875fd0b74Schristos         case OP_lku:
40975fd0b74Schristos           sprintf (operand[i], "#%d", (unsigned) opcode2);
41075fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
41175fd0b74Schristos           break;
41275fd0b74Schristos         case OP_N:
41375fd0b74Schristos           n = (opcode >> 9) & 0x1;
41475fd0b74Schristos           sprintf (operand[i], "st%d", n);
41575fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
41675fd0b74Schristos           break;
41775fd0b74Schristos         case OP_SBIT:
41875fd0b74Schristos         {
41975fd0b74Schristos           const char *status0[] = {
42075fd0b74Schristos             "0", "1", "2", "3", "4", "5", "6", "7", "8",
42175fd0b74Schristos             "ovb", "ova", "c", "tc", "13", "14", "15"
42275fd0b74Schristos           };
42375fd0b74Schristos           const char *status1[] = {
42475fd0b74Schristos             "0", "1", "2", "3", "4",
42575fd0b74Schristos             "cmpt", "frct", "c16", "sxm", "ovm", "10",
42675fd0b74Schristos             "intm", "hm", "xf", "cpl", "braf"
42775fd0b74Schristos           };
42875fd0b74Schristos           sprintf (operand[i], "%s",
42975fd0b74Schristos                    n ? status1[SBIT (opcode)] : status0[SBIT (opcode)]);
43075fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
43175fd0b74Schristos           break;
43275fd0b74Schristos         }
43375fd0b74Schristos         case OP_12:
43475fd0b74Schristos           sprintf (operand[i], "%d", (int) ((opcode >> 9) & 1) + 1);
43575fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
43675fd0b74Schristos           break;
43775fd0b74Schristos         case OP_TRN:
43875fd0b74Schristos           sprintf (operand[i], "trn");
43975fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
44075fd0b74Schristos           break;
44175fd0b74Schristos         case OP_DP:
44275fd0b74Schristos           sprintf (operand[i], "dp");
44375fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
44475fd0b74Schristos           break;
44575fd0b74Schristos         case OP_k9:
44675fd0b74Schristos           /* FIXME-- this is DP, print the original address? */
44775fd0b74Schristos           sprintf (operand[i], "#%d", (int) (opcode & 0x1FF));
44875fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
44975fd0b74Schristos           break;
45075fd0b74Schristos         case OP_ARP:
45175fd0b74Schristos           sprintf (operand[i], "arp");
45275fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
45375fd0b74Schristos           break;
45475fd0b74Schristos         case OP_031:
45575fd0b74Schristos           sprintf (operand[i], "%d", (int) (opcode & 0x1F));
45675fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
45775fd0b74Schristos           break;
45875fd0b74Schristos         default:
45975fd0b74Schristos           sprintf (operand[i], "??? (0x%x)", tm_operands[i]);
46075fd0b74Schristos           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
46175fd0b74Schristos           break;
46275fd0b74Schristos         }
46375fd0b74Schristos       comma = next_comma;
46475fd0b74Schristos     }
46575fd0b74Schristos   return 1;
46675fd0b74Schristos }
46775fd0b74Schristos 
46875fd0b74Schristos static int
print_parallel_instruction(disassemble_info * info,bfd_vma memaddr,unsigned short opcode,const insn_template * ptm,int size)46975fd0b74Schristos print_parallel_instruction (disassemble_info *info,
47075fd0b74Schristos 			    bfd_vma memaddr,
47175fd0b74Schristos 			    unsigned short opcode,
47275fd0b74Schristos 			    const insn_template *ptm,
47375fd0b74Schristos 			    int size)
47475fd0b74Schristos {
47575fd0b74Schristos   print_instruction (info, memaddr, opcode,
47675fd0b74Schristos                      ptm->name, ptm->operand_types, size, 0);
47775fd0b74Schristos   info->fprintf_func (info->stream, " || ");
47875fd0b74Schristos   return print_instruction (info, memaddr, opcode,
47975fd0b74Schristos                             ptm->parname, ptm->paroperand_types, size, 0);
48075fd0b74Schristos }
48175fd0b74Schristos 
48275fd0b74Schristos static int
sprint_dual_address(disassemble_info * info ATTRIBUTE_UNUSED,char buf[],unsigned short code)48375fd0b74Schristos sprint_dual_address (disassemble_info *info ATTRIBUTE_UNUSED,
48475fd0b74Schristos 		     char buf[],
48575fd0b74Schristos 		     unsigned short code)
48675fd0b74Schristos {
48775fd0b74Schristos   const char *formats[] = {
48875fd0b74Schristos     "*ar%d",
48975fd0b74Schristos     "*ar%d-",
49075fd0b74Schristos     "*ar%d+",
49175fd0b74Schristos     "*ar%d+0%%",
49275fd0b74Schristos   };
49375fd0b74Schristos   return sprintf (buf, formats[XMOD (code)], XARX (code));
49475fd0b74Schristos }
49575fd0b74Schristos 
49675fd0b74Schristos static int
sprint_indirect_address(disassemble_info * info ATTRIBUTE_UNUSED,char buf[],unsigned short opcode)49775fd0b74Schristos sprint_indirect_address (disassemble_info *info ATTRIBUTE_UNUSED,
49875fd0b74Schristos 			 char buf[],
49975fd0b74Schristos 			 unsigned short opcode)
50075fd0b74Schristos {
50175fd0b74Schristos   const char *formats[] = {
50275fd0b74Schristos     "*ar%d",
50375fd0b74Schristos     "*ar%d-",
50475fd0b74Schristos     "*ar%d+",
50575fd0b74Schristos     "*+ar%d",
50675fd0b74Schristos     "*ar%d-0B",
50775fd0b74Schristos     "*ar%d-0",
50875fd0b74Schristos     "*ar%d+0",
50975fd0b74Schristos     "*ar%d+0B",
51075fd0b74Schristos     "*ar%d-%%",
51175fd0b74Schristos     "*ar%d-0%%",
51275fd0b74Schristos     "*ar%d+%%",
51375fd0b74Schristos     "*ar%d+0%%",
51475fd0b74Schristos   };
51575fd0b74Schristos   return sprintf (buf, formats[MOD (opcode)], ARF (opcode));
51675fd0b74Schristos }
51775fd0b74Schristos 
51875fd0b74Schristos static int
sprint_direct_address(disassemble_info * info ATTRIBUTE_UNUSED,char buf[],unsigned short opcode)51975fd0b74Schristos sprint_direct_address (disassemble_info *info ATTRIBUTE_UNUSED,
52075fd0b74Schristos 		       char buf[],
52175fd0b74Schristos 		       unsigned short opcode)
52275fd0b74Schristos {
52375fd0b74Schristos   /* FIXME -- look up relocation if available */
52475fd0b74Schristos   return sprintf (buf, "DP+0x%02x", (int) (opcode & 0x7F));
52575fd0b74Schristos }
52675fd0b74Schristos 
52775fd0b74Schristos static int
sprint_mmr(disassemble_info * info ATTRIBUTE_UNUSED,char buf[],int mmr)52875fd0b74Schristos sprint_mmr (disassemble_info *info ATTRIBUTE_UNUSED,
52975fd0b74Schristos 	    char buf[],
53075fd0b74Schristos 	    int mmr)
53175fd0b74Schristos {
532*e992f068Schristos   const tic54x_symbol *reg = tic54x_mmregs;
53375fd0b74Schristos   while (reg->name != NULL)
53475fd0b74Schristos     {
53575fd0b74Schristos       if (mmr == reg->value)
53675fd0b74Schristos         {
53775fd0b74Schristos           sprintf (buf, "%s", (reg + 1)->name);
53875fd0b74Schristos           return 1;
53975fd0b74Schristos         }
54075fd0b74Schristos       ++reg;
54175fd0b74Schristos     }
54275fd0b74Schristos   sprintf (buf, "MMR(%d)", mmr); /* FIXME -- different targets.  */
54375fd0b74Schristos   return 0;
54475fd0b74Schristos }
54575fd0b74Schristos 
54675fd0b74Schristos static int
sprint_cc2(disassemble_info * info ATTRIBUTE_UNUSED,char * buf,unsigned short opcode)54775fd0b74Schristos sprint_cc2 (disassemble_info *info ATTRIBUTE_UNUSED,
54875fd0b74Schristos 	    char *buf,
54975fd0b74Schristos 	    unsigned short opcode)
55075fd0b74Schristos {
55175fd0b74Schristos   const char *cc2[] = {
55275fd0b74Schristos     "??", "??", "ageq", "alt", "aneq", "aeq", "agt", "aleq",
55375fd0b74Schristos     "??", "??", "bgeq", "blt", "bneq", "beq", "bgt", "bleq",
55475fd0b74Schristos   };
55575fd0b74Schristos   return sprintf (buf, "%s", cc2[opcode & 0xF]);
55675fd0b74Schristos }
55775fd0b74Schristos 
55875fd0b74Schristos static int
sprint_condition(disassemble_info * info ATTRIBUTE_UNUSED,char * buf,unsigned short opcode)55975fd0b74Schristos sprint_condition (disassemble_info *info ATTRIBUTE_UNUSED,
56075fd0b74Schristos 		  char *buf,
56175fd0b74Schristos 		  unsigned short opcode)
56275fd0b74Schristos {
56375fd0b74Schristos   char *start = buf;
56475fd0b74Schristos   const char *cmp[] = {
56575fd0b74Schristos       "??", "??", "geq", "lt", "neq", "eq", "gt", "leq"
56675fd0b74Schristos   };
56775fd0b74Schristos   if (opcode & 0x40)
56875fd0b74Schristos     {
56975fd0b74Schristos       char acc = (opcode & 0x8) ? 'b' : 'a';
57075fd0b74Schristos       if (opcode & 0x7)
57175fd0b74Schristos           buf += sprintf (buf, "%c%s%s", acc, cmp[(opcode & 0x7)],
57275fd0b74Schristos                           (opcode & 0x20) ? ", " : "");
57375fd0b74Schristos       if (opcode & 0x20)
57475fd0b74Schristos           buf += sprintf (buf, "%c%s", acc, (opcode & 0x10) ? "ov" : "nov");
57575fd0b74Schristos     }
57675fd0b74Schristos   else if (opcode & 0x3F)
57775fd0b74Schristos     {
57875fd0b74Schristos       if (opcode & 0x30)
57975fd0b74Schristos         buf += sprintf (buf, "%s%s",
58075fd0b74Schristos                         ((opcode & 0x30) == 0x30) ? "tc" : "ntc",
58175fd0b74Schristos                         (opcode & 0x0F) ? ", " : "");
58275fd0b74Schristos       if (opcode & 0x0C)
58375fd0b74Schristos         buf += sprintf (buf, "%s%s",
58475fd0b74Schristos                         ((opcode & 0x0C) == 0x0C) ? "c" : "nc",
58575fd0b74Schristos                         (opcode & 0x03) ? ", " : "");
58675fd0b74Schristos       if (opcode & 0x03)
58775fd0b74Schristos         buf += sprintf (buf, "%s",
58875fd0b74Schristos                         ((opcode & 0x03) == 0x03) ? "bio" : "nbio");
58975fd0b74Schristos     }
59075fd0b74Schristos   else
59175fd0b74Schristos     buf += sprintf (buf, "unc");
59275fd0b74Schristos 
59375fd0b74Schristos   return buf - start;
59475fd0b74Schristos }
595