source: branches/GNU/src/binutils/opcodes/tic80-dis.c@ 11

Last change on this file since 11 was 10, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 10.7 KB
Line 
1/* Print TI TMS320C80 (MVP) instructions
2 Copyright 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
3
4This file is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#include <stdio.h>
19
20#include "sysdep.h"
21#include "opcode/tic80.h"
22#include "dis-asm.h"
23
24static int length;
25
26static void print_operand_bitnum PARAMS ((struct disassemble_info *, long));
27static void print_operand_condition_code PARAMS ((struct disassemble_info *, long));
28static void print_operand_control_register PARAMS ((struct disassemble_info *, long));
29static void print_operand_float PARAMS ((struct disassemble_info *, long));
30static void print_operand_integer PARAMS ((struct disassemble_info *, long));
31static void print_operand PARAMS ((struct disassemble_info *, long, unsigned long,
32 const struct tic80_operand *, bfd_vma));
33static int print_one_instruction PARAMS ((struct disassemble_info *, bfd_vma,
34 unsigned long, const struct tic80_opcode *));
35static int print_instruction PARAMS ((struct disassemble_info *, bfd_vma, unsigned long,
36 const struct tic80_opcode *));
37static int fill_instruction PARAMS ((struct disassemble_info *, bfd_vma,
38 unsigned long *));
39
40
41/* Print an integer operand. Try to be somewhat smart about the
42 format by assuming that small positive or negative integers are
43 probably loop increment values, structure offsets, or similar
44 values that are more meaningful printed as signed decimal values.
45 Larger numbers are probably better printed as hex values. */
46
47static void
48print_operand_integer (info, value)
49 struct disassemble_info *info;
50 long value;
51{
52 if ((value > 9999 || value < -9999))
53 {
54 (*info->fprintf_func) (info->stream, "%#lx", value);
55 }
56 else
57 {
58 (*info->fprintf_func) (info->stream, "%ld", value);
59 }
60}
61
62
63/* FIXME: depends upon sizeof (long) == sizeof (float) and
64 also upon host floating point format matching target
65 floating point format. */
66
67static void
68print_operand_float (info, value)
69 struct disassemble_info *info;
70 long value;
71{
72 union { float f; long l; } fval;
73
74 fval.l = value;
75 (*info->fprintf_func) (info->stream, "%g", fval.f);
76}
77
78
79static void
80print_operand_control_register (info, value)
81 struct disassemble_info *info;
82 long value;
83{
84 const char *tmp;
85
86 tmp = tic80_value_to_symbol (value, TIC80_OPERAND_CR);
87 if (tmp != NULL)
88 {
89 (*info->fprintf_func) (info->stream, "%s", tmp);
90 }
91 else
92 {
93 (*info->fprintf_func) (info->stream, "%#lx", value);
94 }
95}
96
97
98static void
99print_operand_condition_code (info, value)
100 struct disassemble_info *info;
101 long value;
102{
103 const char *tmp;
104
105 tmp = tic80_value_to_symbol (value, TIC80_OPERAND_CC);
106 if (tmp != NULL)
107 {
108 (*info->fprintf_func) (info->stream, "%s", tmp);
109 }
110 else
111 {
112 (*info->fprintf_func) (info->stream, "%ld", value);
113 }
114}
115
116
117static void
118print_operand_bitnum (info, value)
119 struct disassemble_info *info;
120 long value;
121{
122 int bitnum;
123 const char *tmp;
124
125 bitnum = ~value & 0x1F;
126 tmp = tic80_value_to_symbol (bitnum, TIC80_OPERAND_BITNUM);
127 if (tmp != NULL)
128 {
129 (*info->fprintf_func) (info->stream, "%s", tmp);
130 }
131 else
132 {
133 (*info->fprintf_func) (info->stream, "%ld", bitnum);
134 }
135}
136
137
138/* Print the operand as directed by the flags. */
139
140#define M_SI(insn,op) ((((op)->flags & TIC80_OPERAND_M_SI) != 0) && ((insn) & (1 << 17)))
141#define M_LI(insn,op) ((((op)->flags & TIC80_OPERAND_M_LI) != 0) && ((insn) & (1 << 15)))
142#define R_SCALED(insn,op) ((((op)->flags & TIC80_OPERAND_SCALED) != 0) && ((insn) & (1 << 11)))
143
144static void
145print_operand (info, value, insn, operand, memaddr)
146 struct disassemble_info *info;
147 long value;
148 unsigned long insn;
149 const struct tic80_operand *operand;
150 bfd_vma memaddr;
151{
152 if ((operand->flags & TIC80_OPERAND_GPR) != 0)
153 {
154 (*info->fprintf_func) (info->stream, "r%ld", value);
155 if (M_SI (insn, operand) || M_LI (insn, operand))
156 {
157 (*info->fprintf_func) (info->stream, ":m");
158 }
159 }
160 else if ((operand->flags & TIC80_OPERAND_FPA) != 0)
161 {
162 (*info->fprintf_func) (info->stream, "a%ld", value);
163 }
164 else if ((operand->flags & TIC80_OPERAND_PCREL) != 0)
165 {
166 (*info->print_address_func) (memaddr + 4 * value, info);
167 }
168 else if ((operand->flags & TIC80_OPERAND_BASEREL) != 0)
169 {
170 (*info->print_address_func) (value, info);
171 }
172 else if ((operand->flags & TIC80_OPERAND_BITNUM) != 0)
173 {
174 print_operand_bitnum (info, value);
175 }
176 else if ((operand->flags & TIC80_OPERAND_CC) != 0)
177 {
178 print_operand_condition_code (info, value);
179 }
180 else if ((operand->flags & TIC80_OPERAND_CR) != 0)
181 {
182 print_operand_control_register (info, value);
183 }
184 else if ((operand->flags & TIC80_OPERAND_FLOAT) != 0)
185 {
186 print_operand_float (info, value);
187 }
188 else if ((operand->flags & TIC80_OPERAND_BITFIELD))
189 {
190 (*info->fprintf_func) (info->stream, "%#lx", value);
191 }
192 else
193 {
194 print_operand_integer (info, value);
195 }
196
197 /* If this is a scaled operand, then print the modifier. */
198
199 if (R_SCALED (insn, operand))
200 {
201 (*info->fprintf_func) (info->stream, ":s");
202 }
203}
204
205
206/* We have chosen an opcode table entry. */
207
208static int
209print_one_instruction (info, memaddr, insn, opcode)
210 struct disassemble_info *info;
211 bfd_vma memaddr;
212 unsigned long insn;
213 const struct tic80_opcode *opcode;
214{
215 const struct tic80_operand *operand;
216 long value;
217 int status;
218 const unsigned char *opindex;
219 int close_paren;
220
221 (*info->fprintf_func) (info->stream, "%-10s", opcode->name);
222
223 for (opindex = opcode->operands; *opindex != 0; opindex++)
224 {
225 operand = tic80_operands + *opindex;
226
227 /* Extract the value from the instruction. */
228 if (operand->extract)
229 {
230 value = (*operand->extract) (insn, (int *) NULL);
231 }
232 else if (operand->bits == 32)
233 {
234 status = fill_instruction (info, memaddr, (unsigned long *) &value);
235 if (status == -1)
236 {
237 return (status);
238 }
239 }
240 else
241 {
242 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
243 if ((operand->flags & TIC80_OPERAND_SIGNED) != 0
244 && (value & (1 << (operand->bits - 1))) != 0)
245 {
246 value -= 1 << operand->bits;
247 }
248 }
249
250 /* If this operand is enclosed in parenthesis, then print
251 the open paren, otherwise just print the regular comma
252 separator, except for the first operand. */
253
254 if ((operand->flags & TIC80_OPERAND_PARENS) == 0)
255 {
256 close_paren = 0;
257 if (opindex != opcode->operands)
258 {
259 (*info->fprintf_func) (info->stream, ",");
260 }
261 }
262 else
263 {
264 close_paren = 1;
265 (*info->fprintf_func) (info->stream, "(");
266 }
267
268 print_operand (info, value, insn, operand, memaddr);
269
270 /* If we printed an open paren before printing this operand, close
271 it now. The flag gets reset on each loop. */
272
273 if (close_paren)
274 {
275 (*info->fprintf_func) (info->stream, ")");
276 }
277 }
278 return (length);
279}