xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/tic54x-dis.c (revision d2201f2f89f0be1a0be6f7568000ed297414a06d)
15f210c2aSfgsch /* Disassembly routines for TMS320C54X architecture
2*d2201f2fSdrahn    Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
35f210c2aSfgsch    Contributed by Timothy Wall (twall@cygnus.com)
45f210c2aSfgsch 
55f210c2aSfgsch    This program is free software; you can redistribute it and/or modify
65f210c2aSfgsch    it under the terms of the GNU General Public License as published by
75f210c2aSfgsch    the Free Software Foundation; either version 2 of the License, or
85f210c2aSfgsch    (at your option) any later version.
95f210c2aSfgsch 
105f210c2aSfgsch    This program is distributed in the hope that it will be useful,
115f210c2aSfgsch    but WITHOUT ANY WARRANTY; without even the implied warranty of
125f210c2aSfgsch    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
135f210c2aSfgsch    GNU General Public License for more details.
145f210c2aSfgsch 
155f210c2aSfgsch    You should have received a copy of the GNU General Public License
165f210c2aSfgsch    along with this program; if not, write to the Free Software
175f210c2aSfgsch    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
185f210c2aSfgsch    02111-1307, USA.  */
195f210c2aSfgsch 
205f210c2aSfgsch #include <errno.h>
215f210c2aSfgsch #include <math.h>
225f210c2aSfgsch #include <stdlib.h>
235f210c2aSfgsch #include "sysdep.h"
245f210c2aSfgsch #include "dis-asm.h"
255f210c2aSfgsch #include "opcode/tic54x.h"
265f210c2aSfgsch #include "coff/tic54x.h"
275f210c2aSfgsch 
28*d2201f2fSdrahn static int has_lkaddr (unsigned short, const template *);
29*d2201f2fSdrahn static int get_insn_size (unsigned short, const template *);
30*d2201f2fSdrahn static int print_instruction (disassemble_info *, bfd_vma,
31*d2201f2fSdrahn                               unsigned short, const char *,
32*d2201f2fSdrahn                               const enum optype [], int, int);
33*d2201f2fSdrahn static int print_parallel_instruction (disassemble_info *, bfd_vma,
34*d2201f2fSdrahn                                        unsigned short,
35*d2201f2fSdrahn                                        const template *, int);
365f210c2aSfgsch static int sprint_dual_address (disassemble_info *,char [],
375f210c2aSfgsch                                 unsigned short);
385f210c2aSfgsch static int sprint_indirect_address (disassemble_info *,char [],
395f210c2aSfgsch                                     unsigned short);
405f210c2aSfgsch static int sprint_direct_address (disassemble_info *,char [],
415f210c2aSfgsch                                   unsigned short);
425f210c2aSfgsch static int sprint_mmr (disassemble_info *,char [],int);
435f210c2aSfgsch static int sprint_condition (disassemble_info *,char *,unsigned short);
445f210c2aSfgsch static int sprint_cc2 (disassemble_info *,char *,unsigned short);
455f210c2aSfgsch 
465f210c2aSfgsch int
print_insn_tic54x(bfd_vma memaddr,disassemble_info * info)47*d2201f2fSdrahn print_insn_tic54x (bfd_vma memaddr, disassemble_info *info)
485f210c2aSfgsch {
495f210c2aSfgsch   bfd_byte opbuf[2];
505f210c2aSfgsch   unsigned short opcode;
515f210c2aSfgsch   int status, size;
52*d2201f2fSdrahn   const template* tm;
535f210c2aSfgsch 
545f210c2aSfgsch   status = (*info->read_memory_func) (memaddr, opbuf, 2, info);
555f210c2aSfgsch   if (status != 0)
565f210c2aSfgsch   {
575f210c2aSfgsch     (*info->memory_error_func) (status, memaddr, info);
585f210c2aSfgsch     return -1;
595f210c2aSfgsch   }
605f210c2aSfgsch 
615f210c2aSfgsch   opcode = bfd_getl16 (opbuf);
62*d2201f2fSdrahn   tm = tic54x_get_insn (info, memaddr, opcode, &size);
635f210c2aSfgsch 
645f210c2aSfgsch   info->bytes_per_line = 2;
655f210c2aSfgsch   info->bytes_per_chunk = 2;
665f210c2aSfgsch   info->octets_per_byte = 2;
675f210c2aSfgsch   info->display_endian = BFD_ENDIAN_LITTLE;
685f210c2aSfgsch 
69*d2201f2fSdrahn   if (tm->flags & FL_PAR)
705f210c2aSfgsch   {
71*d2201f2fSdrahn     if (!print_parallel_instruction (info, memaddr, opcode, tm, size))
725f210c2aSfgsch       return -1;
735f210c2aSfgsch   }
745f210c2aSfgsch   else
755f210c2aSfgsch   {
765f210c2aSfgsch     if (!print_instruction (info, memaddr, opcode,
77*d2201f2fSdrahn                             (char *) tm->name,
78*d2201f2fSdrahn                             tm->operand_types,
79*d2201f2fSdrahn                             size, (tm->flags & FL_EXT)))
805f210c2aSfgsch       return -1;
815f210c2aSfgsch   }
825f210c2aSfgsch 
835f210c2aSfgsch   return size * 2;
845f210c2aSfgsch }
855f210c2aSfgsch 
865f210c2aSfgsch static int
has_lkaddr(unsigned short memdata,const template * tm)87*d2201f2fSdrahn has_lkaddr (unsigned short memdata, const template *tm)
885f210c2aSfgsch {
89*d2201f2fSdrahn   return (IS_LKADDR (memdata)
90*d2201f2fSdrahn 	  && (OPTYPE (tm->operand_types[0]) == OP_Smem
91*d2201f2fSdrahn 	      || OPTYPE (tm->operand_types[1]) == OP_Smem
92*d2201f2fSdrahn 	      || OPTYPE (tm->operand_types[2]) == OP_Smem
93*d2201f2fSdrahn 	      || OPTYPE (tm->operand_types[1]) == OP_Sind
94*d2201f2fSdrahn               || OPTYPE (tm->operand_types[0]) == OP_Lmem
95*d2201f2fSdrahn               || OPTYPE (tm->operand_types[1]) == OP_Lmem));
965f210c2aSfgsch }
975f210c2aSfgsch 
985f210c2aSfgsch /* always returns 1 (whether an insn template was found) since we provide an
995f210c2aSfgsch    "unknown instruction" template */
100*d2201f2fSdrahn const template*
tic54x_get_insn(disassemble_info * info,bfd_vma addr,unsigned short memdata,int * size)101*d2201f2fSdrahn tic54x_get_insn (disassemble_info *info, bfd_vma addr,
102*d2201f2fSdrahn                  unsigned short memdata, int *size)
1035f210c2aSfgsch {
104*d2201f2fSdrahn   const template *tm = NULL;
1055f210c2aSfgsch 
106*d2201f2fSdrahn   for (tm = tic54x_optab; tm->name; tm++)
1075f210c2aSfgsch   {
108*d2201f2fSdrahn     if (tm->opcode == (memdata & tm->mask))
1095f210c2aSfgsch     {
1105f210c2aSfgsch       /* a few opcodes span two words */
1115f210c2aSfgsch       if (tm->flags & FL_EXT)
1125f210c2aSfgsch         {
1135f210c2aSfgsch           /* if lk addressing is used, the second half of the opcode gets
1145f210c2aSfgsch              pushed one word later */
1155f210c2aSfgsch           bfd_byte opbuf[2];
116*d2201f2fSdrahn           bfd_vma addr2 = addr + 1 + has_lkaddr (memdata, tm);
1175f210c2aSfgsch           int status = (*info->read_memory_func) (addr2, opbuf, 2, info);
118*d2201f2fSdrahn           // FIXME handle errors
1195f210c2aSfgsch           if (status == 0)
1205f210c2aSfgsch             {
121*d2201f2fSdrahn               unsigned short data2 = bfd_getl16 (opbuf);
122*d2201f2fSdrahn               if (tm->opcode2 == (data2 & tm->mask2))
1235f210c2aSfgsch                 {
124*d2201f2fSdrahn                   if (size) *size = get_insn_size (memdata, tm);
125*d2201f2fSdrahn                   return tm;
1265f210c2aSfgsch                 }
1275f210c2aSfgsch             }
1285f210c2aSfgsch         }
1295f210c2aSfgsch       else
1305f210c2aSfgsch         {
131*d2201f2fSdrahn           if (size) *size = get_insn_size (memdata, tm);
132*d2201f2fSdrahn           return tm;
1335f210c2aSfgsch         }
1345f210c2aSfgsch     }
1355f210c2aSfgsch   }
136*d2201f2fSdrahn   for (tm = (template *) tic54x_paroptab; tm->name; tm++)
1375f210c2aSfgsch   {
138*d2201f2fSdrahn     if (tm->opcode == (memdata & tm->mask))
1395f210c2aSfgsch     {
140*d2201f2fSdrahn       if (size) *size = get_insn_size (memdata, tm);
141*d2201f2fSdrahn       return tm;
1425f210c2aSfgsch     }
1435f210c2aSfgsch   }
1445f210c2aSfgsch 
145*d2201f2fSdrahn   if (size) *size = 1;
146*d2201f2fSdrahn   return &tic54x_unknown_opcode;
1475f210c2aSfgsch }
1485f210c2aSfgsch 
1495f210c2aSfgsch static int
get_insn_size(unsigned short memdata,const template * insn)150*d2201f2fSdrahn get_insn_size (unsigned short memdata, const template *insn)
1515f210c2aSfgsch {
1525f210c2aSfgsch   int size;
1535f210c2aSfgsch 
154*d2201f2fSdrahn   if (insn->flags & FL_PAR)
1555f210c2aSfgsch     {
1565f210c2aSfgsch       /* only non-parallel instructions support lk addressing */
157*d2201f2fSdrahn       size = insn->words;
1585f210c2aSfgsch     }
1595f210c2aSfgsch   else
1605f210c2aSfgsch     {
161*d2201f2fSdrahn       size = insn->words + has_lkaddr (memdata, insn);
1625f210c2aSfgsch     }
1635f210c2aSfgsch 
1645f210c2aSfgsch   return size;
1655f210c2aSfgsch }
1665f210c2aSfgsch 
1675f210c2aSfgsch int
print_instruction(info,memaddr,opcode,tm_name,tm_operands,size,ext)1685f210c2aSfgsch print_instruction (info, memaddr, opcode, tm_name, tm_operands, size, ext)
1695f210c2aSfgsch   disassemble_info *info;
1705f210c2aSfgsch   bfd_vma memaddr;
1715f210c2aSfgsch   unsigned short opcode;
172*d2201f2fSdrahn   const char *tm_name;
173*d2201f2fSdrahn   const enum optype tm_operands[];
1745f210c2aSfgsch   int size;
1755f210c2aSfgsch   int ext;
1765f210c2aSfgsch {
1775f210c2aSfgsch   static int n;
1785f210c2aSfgsch   /* string storage for multiple operands */
1795f210c2aSfgsch   char operand[4][64] = { {0},{0},{0},{0}, };
1805f210c2aSfgsch   bfd_byte buf[2];
181*d2201f2fSdrahn   unsigned long opcode2 = 0;
182*d2201f2fSdrahn   unsigned long lkaddr = 0;
1835f210c2aSfgsch   enum optype src = OP_None;
1845f210c2aSfgsch   enum optype dst = OP_None;
1855f210c2aSfgsch   int i, shift;
1865f210c2aSfgsch   char *comma = "";
1875f210c2aSfgsch 
1885f210c2aSfgsch   info->fprintf_func (info->stream, "%-7s", tm_name);
1895f210c2aSfgsch 
1905f210c2aSfgsch   if (size > 1)
1915f210c2aSfgsch     {
1925f210c2aSfgsch       int status = (*info->read_memory_func) (memaddr + 1, buf, 2, info);
1935f210c2aSfgsch       if (status != 0)
1945f210c2aSfgsch         return 0;
1955f210c2aSfgsch       lkaddr = opcode2 = bfd_getl16 (buf);
1965f210c2aSfgsch       if (size > 2)
1975f210c2aSfgsch         {
1985f210c2aSfgsch           status = (*info->read_memory_func) (memaddr + 2, buf, 2, info);
1995f210c2aSfgsch           if (status != 0)
2005f210c2aSfgsch             return 0;
2015f210c2aSfgsch           opcode2 = bfd_getl16 (buf);
2025f210c2aSfgsch         }
2035f210c2aSfgsch     }
2045f210c2aSfgsch 
2055f210c2aSfgsch   for (i = 0; i < MAX_OPERANDS && OPTYPE (tm_operands[i]) != OP_None; i++)
2065f210c2aSfgsch     {
2075f210c2aSfgsch       char *next_comma = ",";
2085f210c2aSfgsch       int optional = (tm_operands[i] & OPT) != 0;
2095f210c2aSfgsch 
2105f210c2aSfgsch       switch (OPTYPE (tm_operands[i]))
2115f210c2aSfgsch         {
2125f210c2aSfgsch         case OP_Xmem:
2135f210c2aSfgsch           sprint_dual_address (info, operand[i], XMEM (opcode));
2145f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
2155f210c2aSfgsch           break;
2165f210c2aSfgsch         case OP_Ymem:
2175f210c2aSfgsch           sprint_dual_address (info, operand[i], YMEM (opcode));
2185f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
2195f210c2aSfgsch           break;
2205f210c2aSfgsch         case OP_Smem:
2215f210c2aSfgsch         case OP_Sind:
2225f210c2aSfgsch         case OP_Lmem:
2235f210c2aSfgsch           info->fprintf_func (info->stream, "%s", comma);
2245f210c2aSfgsch           if (INDIRECT (opcode))
2255f210c2aSfgsch             {
2265f210c2aSfgsch               if (MOD (opcode) >= 12)
2275f210c2aSfgsch                 {
2285f210c2aSfgsch                   bfd_vma addr = lkaddr;
2295f210c2aSfgsch                   int arf = ARF (opcode);
2305f210c2aSfgsch                   int mod = MOD (opcode);
2315f210c2aSfgsch                   if (mod == 15)
2325f210c2aSfgsch                       info->fprintf_func (info->stream, "*(");
2335f210c2aSfgsch                   else
2345f210c2aSfgsch                       info->fprintf_func (info->stream, "*%sar%d(",
2355f210c2aSfgsch                                           (mod == 13 || mod == 14 ? "+" : ""),
2365f210c2aSfgsch                                           arf);
2375f210c2aSfgsch                   (*(info->print_address_func)) ((bfd_vma) addr, info);
2385f210c2aSfgsch                   info->fprintf_func (info->stream, ")%s",
2395f210c2aSfgsch                                       mod == 14 ? "%" : "");
2405f210c2aSfgsch                 }
2415f210c2aSfgsch               else
2425f210c2aSfgsch                 {
2435f210c2aSfgsch                   sprint_indirect_address (info, operand[i], opcode);
2445f210c2aSfgsch                   info->fprintf_func (info->stream, "%s", operand[i]);
2455f210c2aSfgsch                 }
2465f210c2aSfgsch             }
2475f210c2aSfgsch           else
2485f210c2aSfgsch           {
2495f210c2aSfgsch             /* FIXME -- use labels (print_address_func) */
2505f210c2aSfgsch             /* in order to do this, we need to guess what DP is */
2515f210c2aSfgsch             sprint_direct_address (info, operand[i], opcode);
2525f210c2aSfgsch             info->fprintf_func (info->stream, "%s", operand[i]);
2535f210c2aSfgsch           }
2545f210c2aSfgsch           break;
2555f210c2aSfgsch         case OP_dmad:
2565f210c2aSfgsch           info->fprintf_func (info->stream, "%s", comma);
2575f210c2aSfgsch           (*(info->print_address_func)) ((bfd_vma) opcode2, info);
2585f210c2aSfgsch           break;
2595f210c2aSfgsch         case OP_xpmad:
2605f210c2aSfgsch           /* upper 7 bits of address are in the opcode */
2615f210c2aSfgsch           opcode2 += ((unsigned long) opcode & 0x7F) << 16;
2625f210c2aSfgsch           /* fall through */
2635f210c2aSfgsch         case OP_pmad:
2645f210c2aSfgsch           info->fprintf_func (info->stream, "%s", comma);
2655f210c2aSfgsch           (*(info->print_address_func)) ((bfd_vma) opcode2, info);
2665f210c2aSfgsch           break;
2675f210c2aSfgsch         case OP_MMRX:
2685f210c2aSfgsch           sprint_mmr (info, operand[i], MMRX (opcode));
2695f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
2705f210c2aSfgsch           break;
2715f210c2aSfgsch         case OP_MMRY:
2725f210c2aSfgsch           sprint_mmr (info, operand[i], MMRY (opcode));
2735f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
2745f210c2aSfgsch           break;
2755f210c2aSfgsch         case OP_MMR:
2765f210c2aSfgsch           sprint_mmr (info, operand[i], MMR (opcode));
2775f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
2785f210c2aSfgsch           break;
2795f210c2aSfgsch         case OP_PA:
2805f210c2aSfgsch           sprintf (operand[i], "pa%d", (unsigned) opcode2);
2815f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
2825f210c2aSfgsch           break;
2835f210c2aSfgsch         case OP_SRC:
2845f210c2aSfgsch           src = SRC (ext ? opcode2 : opcode) ? OP_B : OP_A;
2855f210c2aSfgsch           sprintf (operand[i], (src == OP_B) ? "b" : "a");
2865f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
2875f210c2aSfgsch           break;
2885f210c2aSfgsch         case OP_SRC1:
2895f210c2aSfgsch           src = SRC1 (ext ? opcode2 : opcode) ? OP_B : OP_A;
2905f210c2aSfgsch           sprintf (operand[i], (src == OP_B) ? "b" : "a");
2915f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
2925f210c2aSfgsch           break;
2935f210c2aSfgsch         case OP_RND:
2945f210c2aSfgsch           dst = DST (opcode) ? OP_B : OP_A;
2955f210c2aSfgsch           sprintf (operand[i], (dst == OP_B) ? "a" : "b");
2965f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
2975f210c2aSfgsch           break;
2985f210c2aSfgsch         case OP_DST:
2995f210c2aSfgsch           dst = DST (ext ? opcode2 : opcode) ? OP_B : OP_A;
3005f210c2aSfgsch           if (!optional || dst != src)
3015f210c2aSfgsch             {
3025f210c2aSfgsch               sprintf (operand[i], (dst == OP_B) ? "b" : "a");
3035f210c2aSfgsch               info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3045f210c2aSfgsch             }
3055f210c2aSfgsch           else
3065f210c2aSfgsch             next_comma = comma;
3075f210c2aSfgsch           break;
3085f210c2aSfgsch         case OP_B:
3095f210c2aSfgsch           sprintf (operand[i], "b");
3105f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3115f210c2aSfgsch           break;
3125f210c2aSfgsch         case OP_A:
3135f210c2aSfgsch           sprintf (operand[i], "a");
3145f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3155f210c2aSfgsch           break;
3165f210c2aSfgsch         case OP_ARX:
3175f210c2aSfgsch           sprintf (operand[i], "ar%d", (int) ARX (opcode));
3185f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3195f210c2aSfgsch           break;
3205f210c2aSfgsch         case OP_SHIFT:
3215f210c2aSfgsch           shift = SHIFT (ext ? opcode2 : opcode);
3225f210c2aSfgsch           if (!optional || shift != 0)
3235f210c2aSfgsch             {
3245f210c2aSfgsch               sprintf (operand[i], "%d", shift);
3255f210c2aSfgsch               info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3265f210c2aSfgsch             }
3275f210c2aSfgsch           else
3285f210c2aSfgsch             next_comma = comma;
3295f210c2aSfgsch           break;
3305f210c2aSfgsch         case OP_SHFT:
3315f210c2aSfgsch           shift = SHFT (opcode);
3325f210c2aSfgsch           if (!optional || shift != 0)
3335f210c2aSfgsch             {
3345f210c2aSfgsch               sprintf (operand[i], "%d", (unsigned) shift);
3355f210c2aSfgsch               info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3365f210c2aSfgsch             }
3375f210c2aSfgsch           else
3385f210c2aSfgsch             next_comma = comma;
3395f210c2aSfgsch           break;
3405f210c2aSfgsch         case OP_lk:
3415f210c2aSfgsch           sprintf (operand[i], "#%d", (int) (short) opcode2);
3425f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3435f210c2aSfgsch           break;
3445f210c2aSfgsch         case OP_T:
3455f210c2aSfgsch           sprintf (operand[i], "t");
3465f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3475f210c2aSfgsch           break;
3485f210c2aSfgsch         case OP_TS:
3495f210c2aSfgsch           sprintf (operand[i], "ts");
3505f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3515f210c2aSfgsch           break;
3525f210c2aSfgsch         case OP_k8:
3535f210c2aSfgsch           sprintf (operand[i], "%d", (int) ((signed char) (opcode & 0xFF)));
3545f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3555f210c2aSfgsch           break;
3565f210c2aSfgsch         case OP_16:
3575f210c2aSfgsch           sprintf (operand[i], "16");
3585f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3595f210c2aSfgsch           break;
3605f210c2aSfgsch         case OP_ASM:
3615f210c2aSfgsch           sprintf (operand[i], "asm");
3625f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3635f210c2aSfgsch           break;
3645f210c2aSfgsch         case OP_BITC:
3655f210c2aSfgsch           sprintf (operand[i], "%d", (int) (opcode & 0xF));
3665f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3675f210c2aSfgsch           break;
3685f210c2aSfgsch         case OP_CC:
3695f210c2aSfgsch           /* put all CC operands in the same operand */
3705f210c2aSfgsch           sprint_condition (info, operand[i], opcode);
3715f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3725f210c2aSfgsch           i = MAX_OPERANDS;
3735f210c2aSfgsch           break;
3745f210c2aSfgsch         case OP_CC2:
3755f210c2aSfgsch           sprint_cc2 (info, operand[i], opcode);
3765f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3775f210c2aSfgsch           break;
3785f210c2aSfgsch         case OP_CC3:
3795f210c2aSfgsch         {
3805f210c2aSfgsch           const char *code[] = { "eq", "lt", "gt", "neq" };
3815f210c2aSfgsch           sprintf (operand[i], code[CC3 (opcode)]);
3825f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3835f210c2aSfgsch           break;
3845f210c2aSfgsch         }
3855f210c2aSfgsch         case OP_123:
3865f210c2aSfgsch           {
3875f210c2aSfgsch             int code = (opcode >> 8) & 0x3;
3885f210c2aSfgsch             sprintf (operand[i], "%d", (code == 0) ? 1 : (code == 2) ? 2 : 3);
3895f210c2aSfgsch             info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3905f210c2aSfgsch             break;
3915f210c2aSfgsch           }
3925f210c2aSfgsch         case OP_k5:
3935f210c2aSfgsch           sprintf (operand[i], "#%d",
3945f210c2aSfgsch                    (int) (((signed char) opcode & 0x1F) << 3) >> 3);
3955f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
3965f210c2aSfgsch           break;
3975f210c2aSfgsch         case OP_k8u:
3985f210c2aSfgsch           sprintf (operand[i], "#%d", (unsigned) (opcode & 0xFF));
3995f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4005f210c2aSfgsch           break;
4015f210c2aSfgsch         case OP_k3:
4025f210c2aSfgsch           sprintf (operand[i], "#%d", (int) (opcode & 0x7));
4035f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4045f210c2aSfgsch           break;
4055f210c2aSfgsch         case OP_lku:
4065f210c2aSfgsch           sprintf (operand[i], "#%d", (unsigned) opcode2);
4075f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4085f210c2aSfgsch           break;
4095f210c2aSfgsch         case OP_N:
4105f210c2aSfgsch           n = (opcode >> 9) & 0x1;
4115f210c2aSfgsch           sprintf (operand[i], "st%d", n);
4125f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4135f210c2aSfgsch           break;
4145f210c2aSfgsch         case OP_SBIT:
4155f210c2aSfgsch         {
4165f210c2aSfgsch           const char *status0[] = {
4175f210c2aSfgsch             "0", "1", "2", "3", "4", "5", "6", "7", "8",
4185f210c2aSfgsch             "ovb", "ova", "c", "tc", "13", "14", "15"
4195f210c2aSfgsch           };
4205f210c2aSfgsch           const char *status1[] = {
4215f210c2aSfgsch             "0", "1", "2", "3", "4",
4225f210c2aSfgsch             "cmpt", "frct", "c16", "sxm", "ovm", "10",
4235f210c2aSfgsch             "intm", "hm", "xf", "cpl", "braf"
4245f210c2aSfgsch           };
4255f210c2aSfgsch           sprintf (operand[i], "%s",
4265f210c2aSfgsch                    n ? status1[SBIT (opcode)] : status0[SBIT (opcode)]);
4275f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4285f210c2aSfgsch           break;
4295f210c2aSfgsch         }
4305f210c2aSfgsch         case OP_12:
4315f210c2aSfgsch           sprintf (operand[i], "%d", (int) ((opcode >> 9) & 1) + 1);
4325f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4335f210c2aSfgsch           break;
4345f210c2aSfgsch         case OP_TRN:
4355f210c2aSfgsch           sprintf (operand[i], "trn");
4365f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4375f210c2aSfgsch           break;
4385f210c2aSfgsch         case OP_DP:
4395f210c2aSfgsch           sprintf (operand[i], "dp");
4405f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4415f210c2aSfgsch           break;
4425f210c2aSfgsch         case OP_k9:
4435f210c2aSfgsch           /* FIXME-- this is DP, print the original address? */
4445f210c2aSfgsch           sprintf (operand[i], "#%d", (int) (opcode & 0x1FF));
4455f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4465f210c2aSfgsch           break;
4475f210c2aSfgsch         case OP_ARP:
4485f210c2aSfgsch           sprintf (operand[i], "arp");
4495f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4505f210c2aSfgsch           break;
4515f210c2aSfgsch         case OP_031:
4525f210c2aSfgsch           sprintf (operand[i], "%d", (int) (opcode & 0x1F));
4535f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4545f210c2aSfgsch           break;
4555f210c2aSfgsch         default:
4565f210c2aSfgsch           sprintf (operand[i], "??? (0x%x)", tm_operands[i]);
4575f210c2aSfgsch           info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
4585f210c2aSfgsch           break;
4595f210c2aSfgsch         }
4605f210c2aSfgsch       comma = next_comma;
4615f210c2aSfgsch     }
4625f210c2aSfgsch   return 1;
4635f210c2aSfgsch }
4645f210c2aSfgsch 
4655f210c2aSfgsch static int
print_parallel_instruction(info,memaddr,opcode,ptm,size)4665f210c2aSfgsch print_parallel_instruction (info, memaddr, opcode, ptm, size)
4675f210c2aSfgsch   disassemble_info *info;
4685f210c2aSfgsch   bfd_vma memaddr;
4695f210c2aSfgsch   unsigned short opcode;
470*d2201f2fSdrahn   const template *ptm;
4715f210c2aSfgsch   int size;
4725f210c2aSfgsch {
4735f210c2aSfgsch   print_instruction (info, memaddr, opcode,
4745f210c2aSfgsch                      ptm->name, ptm->operand_types, size, 0);
4755f210c2aSfgsch   info->fprintf_func (info->stream, " || ");
4765f210c2aSfgsch   return print_instruction (info, memaddr, opcode,
4775f210c2aSfgsch                             ptm->parname, ptm->paroperand_types, size, 0);
4785f210c2aSfgsch }
4795f210c2aSfgsch 
4805f210c2aSfgsch static int
sprint_dual_address(info,buf,code)4815f210c2aSfgsch sprint_dual_address (info, buf, code)
482*d2201f2fSdrahn   disassemble_info *info ATTRIBUTE_UNUSED;
4835f210c2aSfgsch   char buf[];
4845f210c2aSfgsch   unsigned short code;
4855f210c2aSfgsch {
4865f210c2aSfgsch   const char *formats[] = {
4875f210c2aSfgsch     "*ar%d",
4885f210c2aSfgsch     "*ar%d-",
4895f210c2aSfgsch     "*ar%d+",
4905f210c2aSfgsch     "*ar%d+0%%",
4915f210c2aSfgsch   };
4925f210c2aSfgsch   return sprintf (buf, formats[XMOD (code)], XARX (code));
4935f210c2aSfgsch }
4945f210c2aSfgsch 
4955f210c2aSfgsch static int
sprint_indirect_address(info,buf,opcode)4965f210c2aSfgsch sprint_indirect_address (info, buf, opcode)
497*d2201f2fSdrahn   disassemble_info *info ATTRIBUTE_UNUSED;
4985f210c2aSfgsch   char buf[];
4995f210c2aSfgsch   unsigned short opcode;
5005f210c2aSfgsch {
5015f210c2aSfgsch   const char *formats[] = {
5025f210c2aSfgsch     "*ar%d",
5035f210c2aSfgsch     "*ar%d-",
5045f210c2aSfgsch     "*ar%d+",
5055f210c2aSfgsch     "*+ar%d",
5065f210c2aSfgsch     "*ar%d-0B",
5075f210c2aSfgsch     "*ar%d-0",
5085f210c2aSfgsch     "*ar%d+0",
5095f210c2aSfgsch     "*ar%d+0B",
5105f210c2aSfgsch     "*ar%d-%%",
5115f210c2aSfgsch     "*ar%d-0%%",
5125f210c2aSfgsch     "*ar%d+%%",
5135f210c2aSfgsch     "*ar%d+0%%",
5145f210c2aSfgsch   };
5155f210c2aSfgsch   return sprintf (buf, formats[MOD (opcode)], ARF (opcode));
5165f210c2aSfgsch }
5175f210c2aSfgsch 
5185f210c2aSfgsch static int
sprint_direct_address(info,buf,opcode)5195f210c2aSfgsch sprint_direct_address (info, buf, opcode)
520*d2201f2fSdrahn   disassemble_info *info ATTRIBUTE_UNUSED;
5215f210c2aSfgsch   char buf[];
5225f210c2aSfgsch   unsigned short opcode;
5235f210c2aSfgsch {
5245f210c2aSfgsch   /* FIXME -- look up relocation if available */
525*d2201f2fSdrahn   return sprintf (buf, "DP+0x%02x", (int) (opcode & 0x7F));
5265f210c2aSfgsch }
5275f210c2aSfgsch 
5285f210c2aSfgsch static int
sprint_mmr(info,buf,mmr)5295f210c2aSfgsch sprint_mmr (info, buf, mmr)
530*d2201f2fSdrahn   disassemble_info *info ATTRIBUTE_UNUSED;
5315f210c2aSfgsch   char buf[];
5325f210c2aSfgsch   int mmr;
5335f210c2aSfgsch {
5345f210c2aSfgsch   symbol *reg = (symbol *) mmregs;
5355f210c2aSfgsch   while (reg->name != NULL)
5365f210c2aSfgsch     {
5375f210c2aSfgsch       if (mmr == reg->value)
5385f210c2aSfgsch         {
5395f210c2aSfgsch           sprintf (buf, "%s", (reg + 1)->name);
5405f210c2aSfgsch           return 1;
5415f210c2aSfgsch         }
5425f210c2aSfgsch       ++reg;
5435f210c2aSfgsch     }
5445f210c2aSfgsch   sprintf (buf, "MMR(%d)", mmr); /* FIXME -- different targets.  */
5455f210c2aSfgsch   return 0;
5465f210c2aSfgsch }
5475f210c2aSfgsch 
5485f210c2aSfgsch static int
sprint_cc2(info,buf,opcode)5495f210c2aSfgsch sprint_cc2 (info, buf, opcode)
550*d2201f2fSdrahn   disassemble_info *info ATTRIBUTE_UNUSED;
5515f210c2aSfgsch   char *buf;
5525f210c2aSfgsch   unsigned short opcode;
5535f210c2aSfgsch {
5545f210c2aSfgsch   const char *cc2[] = {
5555f210c2aSfgsch     "??", "??", "ageq", "alt", "aneq", "aeq", "agt", "aleq",
5565f210c2aSfgsch     "??", "??", "bgeq", "blt", "bneq", "beq", "bgt", "bleq",
5575f210c2aSfgsch   };
5585f210c2aSfgsch   return sprintf (buf, "%s", cc2[opcode & 0xF]);
5595f210c2aSfgsch }
5605f210c2aSfgsch 
5615f210c2aSfgsch static int
sprint_condition(info,buf,opcode)5625f210c2aSfgsch sprint_condition (info, buf, opcode)
563*d2201f2fSdrahn   disassemble_info *info ATTRIBUTE_UNUSED;
5645f210c2aSfgsch   char *buf;
5655f210c2aSfgsch   unsigned short opcode;
5665f210c2aSfgsch {
5675f210c2aSfgsch   char *start = buf;
5685f210c2aSfgsch   const char *cmp[] = {
5695f210c2aSfgsch       "??", "??", "geq", "lt", "neq", "eq", "gt", "leq"
5705f210c2aSfgsch   };
5715f210c2aSfgsch   if (opcode & 0x40)
5725f210c2aSfgsch     {
5735f210c2aSfgsch       char acc = (opcode & 0x8) ? 'b' : 'a';
5745f210c2aSfgsch       if (opcode & 0x7)
5755f210c2aSfgsch           buf += sprintf (buf, "%c%s%s", acc, cmp[(opcode & 0x7)],
5765f210c2aSfgsch                           (opcode & 0x20) ? ", " : "");
5775f210c2aSfgsch       if (opcode & 0x20)
5785f210c2aSfgsch           buf += sprintf (buf, "%c%s", acc, (opcode & 0x10) ? "ov" : "nov");
5795f210c2aSfgsch     }
5805f210c2aSfgsch   else if (opcode & 0x3F)
5815f210c2aSfgsch     {
5825f210c2aSfgsch       if (opcode & 0x30)
5835f210c2aSfgsch         buf += sprintf (buf, "%s%s",
5845f210c2aSfgsch                         ((opcode & 0x30) == 0x30) ? "tc" : "ntc",
5855f210c2aSfgsch                         (opcode & 0x0F) ? ", " : "");
5865f210c2aSfgsch       if (opcode & 0x0C)
5875f210c2aSfgsch         buf += sprintf (buf, "%s%s",
5885f210c2aSfgsch                         ((opcode & 0x0C) == 0x0C) ? "c" : "nc",
5895f210c2aSfgsch                         (opcode & 0x03) ? ", " : "");
5905f210c2aSfgsch       if (opcode & 0x03)
5915f210c2aSfgsch         buf += sprintf (buf, "%s",
5925f210c2aSfgsch                         ((opcode & 0x03) == 0x03) ? "bio" : "nbio");
5935f210c2aSfgsch     }
5945f210c2aSfgsch   else
5955f210c2aSfgsch     buf += sprintf (buf, "unc");
5965f210c2aSfgsch 
5975f210c2aSfgsch   return buf - start;
5985f210c2aSfgsch }
599