* ppc-opc.c (powerpc_operands): Make comment match the
[external/binutils.git] / opcodes / tic80-dis.c
1 /* Print TI TMS320C80 (MVP) instructions
2    Copyright 1996 Free Software Foundation, Inc.
3
4 This file is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #include <stdio.h>
19
20 #include "ansidecl.h"
21 #include "opcode/tic80.h"
22 #include "dis-asm.h"
23
24 int 
25 print_insn_tic80 (memaddr, info)
26      bfd_vma memaddr;
27      struct disassemble_info *info;
28 {
29   bfd_byte buffer[4];
30   int status;
31   unsigned long insn[2];
32   const struct tic80_opcode *opcode;
33   const struct tic80_opcode *opcode_end;
34   const unsigned char *opindex;
35   const struct tic80_operand *operand;
36   int need_comma;
37   int need_paren;
38   int length = 4;
39
40   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
41   if (status != 0)
42     {
43       (*info->memory_error_func) (status, memaddr, info);
44       return -1;
45     }
46
47   if (info -> endian == BFD_ENDIAN_LITTLE)
48     {
49       insn[0] = bfd_getl32 (buffer);
50     }
51   else if (info -> endian == BFD_ENDIAN_BIG)
52     {
53       insn[0] = bfd_getb32 (buffer);
54     }
55   else
56     {
57       /* FIXME: Should probably just default to one or the other */
58       abort ();
59     }
60
61   /* Find the first opcode match in the opcodes table.  FIXME: there should
62      be faster ways to find one (hash table or binary search), but don't
63      worry too much about it until other TIc80 support is finished. */
64
65   opcode_end = tic80_opcodes + tic80_num_opcodes;
66   for (opcode = tic80_opcodes; opcode < opcode_end; opcode++)
67     {
68       if ((insn[0] & opcode -> mask) == opcode -> opcode)
69         {
70           break;
71         }
72     }
73
74   if (opcode == opcode_end)
75     {
76       /* No match found, just print the bits as a .word directive */
77       (*info -> fprintf_func) (info -> stream, ".word %#08lx", insn[0]);
78     }
79   else
80     {
81       /* Match found, decode the instruction.  */
82       (*info -> fprintf_func) (info -> stream, "%s", opcode -> name);
83
84       /* Now extract and print the operands. */
85       need_comma = 0;
86       need_paren = 0;
87       if (opcode -> operands[0] != 0)
88         {
89           (*info -> fprintf_func) (info -> stream, "\t");
90         }
91       for (opindex = opcode -> operands; *opindex != 0; opindex++)
92         {
93           long value;
94
95           operand = tic80_operands + *opindex;
96
97           /* Extract the value from the instruction.  */
98           if (operand -> extract)
99             {
100               value = (*operand -> extract) (insn[0], (int *) NULL);
101             }
102           else if (operand -> bits == 32)
103             {
104               status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
105               if (status != 0)
106                 {
107                   (*info->memory_error_func) (status, memaddr, info);
108                   return -1;
109                 }
110
111               if (info -> endian == BFD_ENDIAN_LITTLE)
112                 {
113                   insn[1] = bfd_getl32 (buffer);
114                 }
115               else if (info -> endian == BFD_ENDIAN_BIG)
116                 {
117                   insn[1] = bfd_getb32 (buffer);
118                 }
119               value = (long) insn[1];
120               length += 4;
121             }
122           else
123             {
124               value = (insn[0] >> operand -> shift) & ((1 << operand -> bits) - 1);
125               if ((operand -> flags & TIC80_OPERAND_SIGNED) != 0
126                   && (value & (1 << (operand -> bits - 1))) != 0)
127                 value -= 1 << operand -> bits;
128             }
129
130           if (need_comma)
131             {
132               (*info -> fprintf_func) (info -> stream, ",");
133               need_comma = 0;
134             }
135
136           /* Print the operand as directed by the flags.  */
137           if ((operand -> flags & TIC80_OPERAND_GPR) != 0)
138             {
139               (*info -> fprintf_func) (info -> stream, "r%ld", value);
140             }
141           else if ((operand -> flags & TIC80_OPERAND_FPA) != 0)
142             {
143               (*info -> fprintf_func) (info -> stream, "a%ld", value);
144             }
145           else if ((operand -> flags & TIC80_OPERAND_RELATIVE) != 0)
146             {
147               (*info -> print_address_func) (memaddr + value, info);
148             }
149           else if ((operand -> flags & TIC80_OPERAND_CC_SZ) != 0)
150             {
151 #if 0   /* FIXME */           
152               if (operand -> bits == 3)
153                 (*info -> fprintf_func) (info -> stream, "cr%d", value);
154               else
155                 {
156                   static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
157                   int cr;
158                   int cc;
159
160                   cr = value >> 2;
161                   if (cr != 0)
162                     (*info -> fprintf_func) (info -> stream, "4*cr%d", cr);
163                   cc = value & 3;
164                   if (cc != 0)
165                     {
166                       if (cr != 0)
167                         (*info -> fprintf_func) (info -> stream, "+");
168                       (*info -> fprintf_func) (info -> stream, "%s", cbnames[cc]);
169                     }
170                 }
171 #endif
172             }
173           else
174             {
175               if ((value > 999 || value < -999)
176                   || operand -> flags & TIC80_OPERAND_BITFIELD)
177                 {
178                   (*info -> fprintf_func) (info -> stream, "%#lx", value);
179                 }
180               else
181                 {
182                   (*info -> fprintf_func) (info -> stream, "%ld", value);
183                 }
184             }
185
186           if (need_paren)
187             {
188               (*info -> fprintf_func) (info -> stream, ")");
189               need_paren = 0;
190             }
191
192           if ((operand -> flags & TIC80_OPERAND_PARENS) == 0)
193             {
194               need_comma = 1;
195             }
196           else
197             {
198               (*info -> fprintf_func) (info -> stream, "(");
199               need_paren = 1;
200             }
201         }
202     }
203
204   return (length);
205 }