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