1 /* Print TI TMS320C80 (MVP) instructions
2 Copyright 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
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.
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.
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. */
21 #include "opcode/tic80.h"
26 static void print_operand_bitnum
PARAMS ((struct disassemble_info
*, long));
27 static void print_operand_condition_code
PARAMS ((struct disassemble_info
*, long));
28 static void print_operand_control_register
PARAMS ((struct disassemble_info
*, long));
29 static void print_operand_float
PARAMS ((struct disassemble_info
*, long));
30 static void print_operand_integer
PARAMS ((struct disassemble_info
*, long));
31 static void print_operand
PARAMS ((struct disassemble_info
*, long, unsigned long,
32 const struct tic80_operand
*, bfd_vma
));
33 static int print_one_instruction
PARAMS ((struct disassemble_info
*, bfd_vma
,
34 unsigned long, const struct tic80_opcode
*));
35 static int print_instruction
PARAMS ((struct disassemble_info
*, bfd_vma
, unsigned long,
36 const struct tic80_opcode
*));
37 static int fill_instruction
PARAMS ((struct disassemble_info
*, bfd_vma
,
40 /* Print an integer operand. Try to be somewhat smart about the
41 format by assuming that small positive or negative integers are
42 probably loop increment values, structure offsets, or similar
43 values that are more meaningful printed as signed decimal values.
44 Larger numbers are probably better printed as hex values. */
47 print_operand_integer (info
, value
)
48 struct disassemble_info
*info
;
51 if ((value
> 9999 || value
< -9999))
53 (*info
->fprintf_func
) (info
->stream
, "%#lx", value
);
57 (*info
->fprintf_func
) (info
->stream
, "%ld", value
);
61 /* FIXME: depends upon sizeof (long) == sizeof (float) and
62 also upon host floating point format matching target
63 floating point format. */
66 print_operand_float (info
, value
)
67 struct disassemble_info
*info
;
70 union { float f
; long l
; } fval
;
73 (*info
->fprintf_func
) (info
->stream
, "%g", fval
.f
);
77 print_operand_control_register (info
, value
)
78 struct disassemble_info
*info
;
83 tmp
= tic80_value_to_symbol (value
, TIC80_OPERAND_CR
);
86 (*info
->fprintf_func
) (info
->stream
, "%s", tmp
);
90 (*info
->fprintf_func
) (info
->stream
, "%#lx", value
);
95 print_operand_condition_code (info
, value
)
96 struct disassemble_info
*info
;
101 tmp
= tic80_value_to_symbol (value
, TIC80_OPERAND_CC
);
104 (*info
->fprintf_func
) (info
->stream
, "%s", tmp
);
108 (*info
->fprintf_func
) (info
->stream
, "%ld", value
);
113 print_operand_bitnum (info
, value
)
114 struct disassemble_info
*info
;
120 bitnum
= ~value
& 0x1F;
121 tmp
= tic80_value_to_symbol (bitnum
, TIC80_OPERAND_BITNUM
);
124 (*info
->fprintf_func
) (info
->stream
, "%s", tmp
);
128 (*info
->fprintf_func
) (info
->stream
, "%ld", bitnum
);
132 /* Print the operand as directed by the flags. */
134 #define M_SI(insn,op) ((((op)->flags & TIC80_OPERAND_M_SI) != 0) && ((insn) & (1 << 17)))
135 #define M_LI(insn,op) ((((op)->flags & TIC80_OPERAND_M_LI) != 0) && ((insn) & (1 << 15)))
136 #define R_SCALED(insn,op) ((((op)->flags & TIC80_OPERAND_SCALED) != 0) && ((insn) & (1 << 11)))
139 print_operand (info
, value
, insn
, operand
, memaddr
)
140 struct disassemble_info
*info
;
143 const struct tic80_operand
*operand
;
146 if ((operand
->flags
& TIC80_OPERAND_GPR
) != 0)
148 (*info
->fprintf_func
) (info
->stream
, "r%ld", value
);
149 if (M_SI (insn
, operand
) || M_LI (insn
, operand
))
151 (*info
->fprintf_func
) (info
->stream
, ":m");
154 else if ((operand
->flags
& TIC80_OPERAND_FPA
) != 0)
156 (*info
->fprintf_func
) (info
->stream
, "a%ld", value
);
158 else if ((operand
->flags
& TIC80_OPERAND_PCREL
) != 0)
160 (*info
->print_address_func
) (memaddr
+ 4 * value
, info
);
162 else if ((operand
->flags
& TIC80_OPERAND_BASEREL
) != 0)
164 (*info
->print_address_func
) (value
, info
);
166 else if ((operand
->flags
& TIC80_OPERAND_BITNUM
) != 0)
168 print_operand_bitnum (info
, value
);
170 else if ((operand
->flags
& TIC80_OPERAND_CC
) != 0)
172 print_operand_condition_code (info
, value
);
174 else if ((operand
->flags
& TIC80_OPERAND_CR
) != 0)
176 print_operand_control_register (info
, value
);
178 else if ((operand
->flags
& TIC80_OPERAND_FLOAT
) != 0)
180 print_operand_float (info
, value
);
182 else if ((operand
->flags
& TIC80_OPERAND_BITFIELD
))
184 (*info
->fprintf_func
) (info
->stream
, "%#lx", value
);
188 print_operand_integer (info
, value
);
191 /* If this is a scaled operand, then print the modifier. */
193 if (R_SCALED (insn
, operand
))
195 (*info
->fprintf_func
) (info
->stream
, ":s");
199 /* We have chosen an opcode table entry. */
202 print_one_instruction (info
, memaddr
, insn
, opcode
)
203 struct disassemble_info
*info
;
206 const struct tic80_opcode
*opcode
;
208 const struct tic80_operand
*operand
;
211 const unsigned char *opindex
;
214 (*info
->fprintf_func
) (info
->stream
, "%-10s", opcode
->name
);
216 for (opindex
= opcode
->operands
; *opindex
!= 0; opindex
++)
218 operand
= tic80_operands
+ *opindex
;
220 /* Extract the value from the instruction. */
221 if (operand
->extract
)
223 value
= (*operand
->extract
) (insn
, (int *) NULL
);
225 else if (operand
->bits
== 32)
227 status
= fill_instruction (info
, memaddr
, (unsigned long *) &value
);
235 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
236 if ((operand
->flags
& TIC80_OPERAND_SIGNED
) != 0
237 && (value
& (1 << (operand
->bits
- 1))) != 0)
239 value
-= 1 << operand
->bits
;
243 /* If this operand is enclosed in parenthesis, then print
244 the open paren, otherwise just print the regular comma
245 separator, except for the first operand. */
247 if ((operand
->flags
& TIC80_OPERAND_PARENS
) == 0)
250 if (opindex
!= opcode
->operands
)
252 (*info
->fprintf_func
) (info
->stream
, ",");
258 (*info
->fprintf_func
) (info
->stream
, "(");
261 print_operand (info
, value
, insn
, operand
, memaddr
);
263 /* If we printed an open paren before printing this operand, close
264 it now. The flag gets reset on each loop. */
268 (*info
->fprintf_func
) (info
->stream
, ")");
274 /* There are no specific bits that tell us for certain whether a vector
275 instruction opcode contains one or two instructions. However since
276 a destination register of r0 is illegal, we can check for nonzero
277 values in both destination register fields. Only opcodes that have
278 two valid instructions will have non-zero in both. */
280 #define TWO_INSN(insn) ((((insn) & (0x1F << 27)) != 0) && (((insn) & (0x1F << 22)) != 0))
283 print_instruction (info
, memaddr
, insn
, vec_opcode
)
284 struct disassemble_info
*info
;
287 const struct tic80_opcode
*vec_opcode
;
289 const struct tic80_opcode
*opcode
;
290 const struct tic80_opcode
*opcode_end
;
292 /* Find the first opcode match in the opcodes table. For vector
293 opcodes (vec_opcode != NULL) find the first match that is not the
294 previously found match. FIXME: there should be faster ways to
295 search (hash table or binary search), but don't worry too much
296 about it until other TIc80 support is finished. */
298 opcode_end
= tic80_opcodes
+ tic80_num_opcodes
;
299 for (opcode
= tic80_opcodes
; opcode
< opcode_end
; opcode
++)
301 if ((insn
& opcode
->mask
) == opcode
->opcode
&&
302 opcode
!= vec_opcode
)
308 if (opcode
== opcode_end
)
310 /* No match found, just print the bits as a .word directive. */
311 (*info
->fprintf_func
) (info
->stream
, ".word %#08lx", insn
);
315 /* Match found, decode the instruction. */
316 length
= print_one_instruction (info
, memaddr
, insn
, opcode
);
317 if (opcode
->flags
& TIC80_VECTOR
&& vec_opcode
== NULL
&& TWO_INSN (insn
))
319 /* There is another instruction to print from the same opcode.
320 Print the separator and then find and print the other
322 (*info
->fprintf_func
) (info
->stream
, " || ");
323 length
= print_instruction (info
, memaddr
, insn
, opcode
);
329 /* Get the next 32 bit word from the instruction stream and convert it
330 into internal format in the unsigned long INSN, for which we are
331 passed the address. Return 0 on success, -1 on error. */
334 fill_instruction (info
, memaddr
, insnp
)
335 struct disassemble_info
*info
;
337 unsigned long *insnp
;
342 /* Get the bits for the next 32 bit word and put in buffer. */
344 status
= (*info
->read_memory_func
) (memaddr
+ length
, buffer
, 4, info
);
347 (*info
->memory_error_func
) (status
, memaddr
, info
);
351 /* Read was successful, so increment count of bytes read and convert
352 the bits into internal format. */
355 if (info
->endian
== BFD_ENDIAN_LITTLE
)
357 *insnp
= bfd_getl32 (buffer
);
359 else if (info
->endian
== BFD_ENDIAN_BIG
)
361 *insnp
= bfd_getb32 (buffer
);
365 /* FIXME: Should probably just default to one or the other. */
372 print_insn_tic80 (memaddr
, info
)
374 struct disassemble_info
*info
;
380 info
->bytes_per_line
= 8;
381 status
= fill_instruction (info
, memaddr
, &insn
);
384 status
= print_instruction (info
, memaddr
, insn
, NULL
);