1 /* Print TI TMS320C80 (MVP) instructions
2 Copyright 1996, 1997 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
,
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. */
48 print_operand_integer (info
, value
)
49 struct disassemble_info
*info
;
52 if ((value
> 9999 || value
< -9999))
54 (*info
-> fprintf_func
) (info
-> stream
, "%#lx", value
);
58 (*info
-> fprintf_func
) (info
-> stream
, "%ld", value
);
63 /* FIXME: depends upon sizeof (long) == sizeof (float) and
64 also upon host floating point format matching target
65 floating point format. */
68 print_operand_float (info
, value
)
69 struct disassemble_info
*info
;
72 union { float f
; long l
; } fval
;
75 (*info
-> fprintf_func
) (info
-> stream
, "%g", fval
.f
);
80 print_operand_control_register (info
, value
)
81 struct disassemble_info
*info
;
86 tmp
= tic80_value_to_symbol (value
, TIC80_OPERAND_CR
);
89 (*info
-> fprintf_func
) (info
-> stream
, "%s", tmp
);
93 (*info
-> fprintf_func
) (info
-> stream
, "%#lx", value
);
99 print_operand_condition_code (info
, value
)
100 struct disassemble_info
*info
;
105 tmp
= tic80_value_to_symbol (value
, TIC80_OPERAND_CC
);
108 (*info
-> fprintf_func
) (info
-> stream
, "%s", tmp
);
112 (*info
-> fprintf_func
) (info
-> stream
, "%ld", value
);
118 print_operand_bitnum (info
, value
)
119 struct disassemble_info
*info
;
125 bitnum
= ~value
& 0x1F;
126 tmp
= tic80_value_to_symbol (bitnum
, TIC80_OPERAND_BITNUM
);
129 (*info
-> fprintf_func
) (info
-> stream
, "%s", tmp
);
133 (*info
-> fprintf_func
) (info
-> stream
, "%ld", bitnum
);
138 /* Print the operand as directed by the flags. */
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)))
145 print_operand (info
, value
, insn
, operand
, memaddr
)
146 struct disassemble_info
*info
;
149 const struct tic80_operand
*operand
;
152 if ((operand
-> flags
& TIC80_OPERAND_GPR
) != 0)
154 (*info
-> fprintf_func
) (info
-> stream
, "r%ld", value
);
155 if (M_SI (insn
, operand
) || M_LI (insn
, operand
))
157 (*info
-> fprintf_func
) (info
-> stream
, ":m");
160 else if ((operand
-> flags
& TIC80_OPERAND_FPA
) != 0)
162 (*info
-> fprintf_func
) (info
-> stream
, "a%ld", value
);
164 else if ((operand
-> flags
& TIC80_OPERAND_PCREL
) != 0)
166 (*info
-> print_address_func
) (memaddr
+ 4 * value
, info
);
168 else if ((operand
-> flags
& TIC80_OPERAND_BASEREL
) != 0)
170 (*info
-> print_address_func
) (value
, info
);
172 else if ((operand
-> flags
& TIC80_OPERAND_BITNUM
) != 0)
174 print_operand_bitnum (info
, value
);
176 else if ((operand
-> flags
& TIC80_OPERAND_CC
) != 0)
178 print_operand_condition_code (info
, value
);
180 else if ((operand
-> flags
& TIC80_OPERAND_CR
) != 0)
182 print_operand_control_register (info
, value
);
184 else if ((operand
-> flags
& TIC80_OPERAND_FLOAT
) != 0)
186 print_operand_float (info
, value
);
188 else if ((operand
-> flags
& TIC80_OPERAND_BITFIELD
))
190 (*info
-> fprintf_func
) (info
-> stream
, "%#lx", value
);
194 print_operand_integer (info
, value
);
197 /* If this is a scaled operand, then print the modifier */
199 if (R_SCALED (insn
, operand
))
201 (*info
-> fprintf_func
) (info
-> stream
, ":s");
206 /* We have chosen an opcode table entry */
209 print_one_instruction (info
, memaddr
, insn
, opcode
)
210 struct disassemble_info
*info
;
213 const struct tic80_opcode
*opcode
;
215 const struct tic80_operand
*operand
;
218 const unsigned char *opindex
;
222 (*info
-> fprintf_func
) (info
-> stream
, "%-10s", opcode
-> name
);
224 for (opindex
= opcode
-> operands
; *opindex
!= 0; opindex
++)
226 operand
= tic80_operands
+ *opindex
;
228 /* Extract the value from the instruction. */
229 if (operand
-> extract
)
231 value
= (*operand
-> extract
) (insn
, (int *) NULL
);
233 else if (operand
-> bits
== 32)
235 status
= fill_instruction (info
, memaddr
, (unsigned long *) &value
);
243 value
= (insn
>> operand
-> shift
) & ((1 << operand
-> bits
) - 1);
244 if ((operand
-> flags
& TIC80_OPERAND_SIGNED
) != 0
245 && (value
& (1 << (operand
-> bits
- 1))) != 0)
247 value
-= 1 << operand
-> bits
;
251 /* If this operand is enclosed in parenthesis, then print
252 the open paren, otherwise just print the regular comma
253 separator, except for the first operand. */
255 if ((operand
-> flags
& TIC80_OPERAND_PARENS
) == 0)
258 if (opindex
!= opcode
-> operands
)
260 (*info
-> fprintf_func
) (info
-> stream
, ",");
266 (*info
-> fprintf_func
) (info
-> stream
, "(");
269 print_operand (info
, value
, insn
, operand
, memaddr
);
271 /* If we printed an open paren before printing this operand, close
272 it now. The flag gets reset on each loop. */
276 (*info
-> fprintf_func
) (info
-> stream
, ")");
284 /* There are no specific bits that tell us for certain whether a vector
285 instruction opcode contains one or two instructions. However since
286 a destination register of r0 is illegal, we can check for nonzero
287 values in both destination register fields. Only opcodes that have
288 two valid instructions will have non-zero in both */
290 #define TWO_INSN(insn) ((((insn) & (0x1F << 27)) != 0) && (((insn) & (0x1F << 22)) != 0))
293 print_instruction (info
, memaddr
, insn
, vec_opcode
)
294 struct disassemble_info
*info
;
297 const struct tic80_opcode
*vec_opcode
;
299 const struct tic80_opcode
*opcode
;
300 const struct tic80_opcode
*opcode_end
;
302 /* Find the first opcode match in the opcodes table. For vector
303 opcodes (vec_opcode != NULL) find the first match that is not the
304 previously found match. FIXME: there should be faster ways to
305 search (hash table or binary search), but don't worry too much
306 about it until other TIc80 support is finished. */
308 opcode_end
= tic80_opcodes
+ tic80_num_opcodes
;
309 for (opcode
= tic80_opcodes
; opcode
< opcode_end
; opcode
++)
311 if ((insn
& opcode
-> mask
) == opcode
-> opcode
&&
312 opcode
!= vec_opcode
)
318 if (opcode
== opcode_end
)
320 /* No match found, just print the bits as a .word directive */
321 (*info
-> fprintf_func
) (info
-> stream
, ".word %#08lx", insn
);
325 /* Match found, decode the instruction. */
326 length
= print_one_instruction (info
, memaddr
, insn
, opcode
);
327 if (opcode
-> flags
& TIC80_VECTOR
&& vec_opcode
== NULL
&& TWO_INSN (insn
))
329 /* There is another instruction to print from the same opcode.
330 Print the separator and then find and print the other
332 (*info
-> fprintf_func
) (info
-> stream
, " || ");
333 length
= print_instruction (info
, memaddr
, insn
, opcode
);
339 /* Get the next 32 bit word from the instruction stream and convert it
340 into internal format in the unsigned long INSN, for which we are
341 passed the address. Return 0 on success, -1 on error. */
344 fill_instruction (info
, memaddr
, insnp
)
345 struct disassemble_info
*info
;
347 unsigned long *insnp
;
352 /* Get the bits for the next 32 bit word and put in buffer */
354 status
= (*info
-> read_memory_func
) (memaddr
+ length
, buffer
, 4, info
);
357 (*info
-> memory_error_func
) (status
, memaddr
, info
);
361 /* Read was successful, so increment count of bytes read and convert
362 the bits into internal format. */
365 if (info
-> endian
== BFD_ENDIAN_LITTLE
)
367 *insnp
= bfd_getl32 (buffer
);
369 else if (info
-> endian
== BFD_ENDIAN_BIG
)
371 *insnp
= bfd_getb32 (buffer
);
375 /* FIXME: Should probably just default to one or the other */
383 print_insn_tic80 (memaddr
, info
)
385 struct disassemble_info
*info
;
391 status
= fill_instruction (info
, memaddr
, &insn
);
394 status
= print_instruction (info
, memaddr
, insn
, NULL
);