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