1 /* Print TI TMS320C80 (MVP) instructions
2 Copyright 1996 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"
24 #define M_SI(insn,op) ((((op) -> flags & TIC80_OPERAND_M_SI) != 0) && ((insn) & (1 << 17)))
25 #define M_LI(insn,op) ((((op) -> flags & TIC80_OPERAND_M_LI) != 0) && ((insn) & (1 << 15)))
26 #define R_SCALED(insn,op) ((((op) -> flags & TIC80_OPERAND_SCALED) != 0) && ((insn) & (1 << 11)))
29 print_insn_tic80 (memaddr
, info
)
31 struct disassemble_info
*info
;
35 unsigned long insn
[2];
36 const struct tic80_opcode
*opcode
;
37 const struct tic80_opcode
*opcode_end
;
38 const unsigned char *opindex
;
39 const struct tic80_operand
*operand
;
43 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
46 (*info
->memory_error_func
) (status
, memaddr
, info
);
50 if (info
-> endian
== BFD_ENDIAN_LITTLE
)
52 insn
[0] = bfd_getl32 (buffer
);
54 else if (info
-> endian
== BFD_ENDIAN_BIG
)
56 insn
[0] = bfd_getb32 (buffer
);
60 /* FIXME: Should probably just default to one or the other */
64 /* Find the first opcode match in the opcodes table. FIXME: there should
65 be faster ways to find one (hash table or binary search), but don't
66 worry too much about it until other TIc80 support is finished. */
68 opcode_end
= tic80_opcodes
+ tic80_num_opcodes
;
69 for (opcode
= tic80_opcodes
; opcode
< opcode_end
; opcode
++)
71 if ((insn
[0] & opcode
-> mask
) == opcode
-> opcode
)
77 if (opcode
== opcode_end
)
79 /* No match found, just print the bits as a .word directive */
80 (*info
-> fprintf_func
) (info
-> stream
, ".word %#08lx", insn
[0]);
84 /* Match found, decode the instruction. */
85 (*info
-> fprintf_func
) (info
-> stream
, "%s", opcode
-> name
);
87 /* Now extract and print the operands. */
88 if (opcode
-> operands
[0] != 0)
90 (*info
-> fprintf_func
) (info
-> stream
, "\t");
92 for (opindex
= opcode
-> operands
; *opindex
!= 0; opindex
++)
96 operand
= tic80_operands
+ *opindex
;
98 /* Extract the value from the instruction. */
99 if (operand
-> extract
)
101 value
= (*operand
-> extract
) (insn
[0], (int *) NULL
);
103 else if (operand
-> bits
== 32)
105 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 4, info
);
108 (*info
->memory_error_func
) (status
, memaddr
, info
);
112 if (info
-> endian
== BFD_ENDIAN_LITTLE
)
114 insn
[1] = bfd_getl32 (buffer
);
116 else if (info
-> endian
== BFD_ENDIAN_BIG
)
118 insn
[1] = bfd_getb32 (buffer
);
120 value
= (long) insn
[1];
125 value
= (insn
[0] >> operand
-> shift
) & ((1 << operand
-> bits
) - 1);
126 if ((operand
-> flags
& TIC80_OPERAND_SIGNED
) != 0
127 && (value
& (1 << (operand
-> bits
- 1))) != 0)
128 value
-= 1 << operand
-> bits
;
131 /* If this operand is enclosed in parenthesis, then print
132 the open paren, otherwise just print the regular comma
133 separator, except for the first operand. */
135 if ((operand
-> flags
& TIC80_OPERAND_PARENS
) == 0)
138 if (opindex
!= opcode
-> operands
)
140 (*info
-> fprintf_func
) (info
-> stream
, ",");
146 (*info
-> fprintf_func
) (info
-> stream
, "(");
149 /* Print the operand as directed by the flags. */
151 if ((operand
-> flags
& TIC80_OPERAND_GPR
) != 0)
153 (*info
-> fprintf_func
) (info
-> stream
, "r%ld", value
);
154 if (M_SI (insn
[0], operand
) || M_LI (insn
[0], operand
))
156 (*info
-> fprintf_func
) (info
-> stream
, ":m");
159 else if ((operand
-> flags
& TIC80_OPERAND_FPA
) != 0)
161 (*info
-> fprintf_func
) (info
-> stream
, "a%ld", value
);
163 else if ((operand
-> flags
& TIC80_OPERAND_RELATIVE
) != 0)
165 (*info
-> print_address_func
) (memaddr
+ 4 * value
, info
);
167 else if ((operand
-> flags
& TIC80_OPERAND_BITNUM
) != 0)
170 "eq.b", "ne.b", "gt.b", "le.b", "lt.b", "ge.b",
171 "hi.b", "ls.b", "lo.b", "hs.b", "eq.h", "ne.h",
172 "gt.h", "le.h", "lt.h", "ge.h", "hi.h", "ls.h",
173 "lo.h", "hs.h", "eq.w", "ne.w", "gt.w", "le.w",
174 "lt.w", "ge.w", "hi.w", "ls.w", "lo.w", "hs.w"
176 int bitnum
= ~value
& 0x1F;
180 /* Found a value within range */
181 (*info
-> fprintf_func
) (info
-> stream
, "%s", syms
[bitnum
]);
185 /* Not in range, just print as bit number */
186 (*info
-> fprintf_func
) (info
-> stream
, "%ld", bitnum
);
189 else if ((operand
-> flags
& TIC80_OPERAND_CC
) != 0)
192 "nev.b", "gt0.b", "eq0.b", "ge0.b", "lt0.b", "ne0.b", "le0.b", "alw.b",
193 "nev.h", "gt0.h", "eq0.h", "ge0.h", "lt0.h", "ne0.h", "le0.h", "alw.h",
194 "nev.w", "gt0.w", "eq0.w", "ge0.w", "lt0.w", "ne0.w", "le0.w", "alw.w"
198 /* Found a value within range */
199 (*info
-> fprintf_func
) (info
-> stream
, "%s", syms
[value
]);
203 /* Not in range, just print as decimal digit. */
204 (*info
-> fprintf_func
) (info
-> stream
, "%ld", value
);
207 else if ((operand
-> flags
& TIC80_OPERAND_CR
) != 0)
212 case 0: tmp
= "EPC"; break;
213 case 1: tmp
= "EIP"; break;
214 case 2: tmp
= "CONFIG"; break;
215 case 4: tmp
= "INTPEN"; break;
216 case 6: tmp
= "IE"; break;
217 case 8: tmp
= "FPST"; break;
218 case 0xA: tmp
= "PPERROR"; break;
219 case 0xD: tmp
= "PKTREQ"; break;
220 case 0xE: tmp
= "TCOUNT"; break;
221 case 0xF: tmp
= "TSCALE"; break;
222 case 0x10: tmp
= "FLTOP"; break;
223 case 0x11: tmp
= "FLTADR"; break;
224 case 0x12: tmp
= "FLTTAG"; break;
225 case 0x13: tmp
= "FLTDTL"; break;
226 case 0x14: tmp
= "FLTDTH"; break;
227 case 0x20: tmp
= "SYSSTK"; break;
228 case 0x21: tmp
= "SYSTMP"; break;
229 case 0x30: tmp
= "MPC"; break;
230 case 0x31: tmp
= "MIP"; break;
231 case 0x33: tmp
= "ECOMCNTL"; break;
232 case 0x34: tmp
= "ANASTAT"; break;
233 case 0x39: tmp
= "BRK1"; break;
234 case 0x3A: tmp
= "BRK2"; break;
235 case 0x200: tmp
= "ITAG0"; break;
236 case 0x201: tmp
= "ITAG1"; break;
237 case 0x202: tmp
= "ITAG2"; break;
238 case 0x203: tmp
= "ITAG3"; break;
239 case 0x204: tmp
= "ITAG4"; break;
240 case 0x205: tmp
= "ITAG5"; break;
241 case 0x206: tmp
= "ITAG6"; break;
242 case 0x207: tmp
= "ITAG7"; break;
243 case 0x208: tmp
= "ITAG8"; break;
244 case 0x209: tmp
= "ITAG9"; break;
245 case 0x20A: tmp
= "ITAG10"; break;
246 case 0x20B: tmp
= "ITAG11"; break;
247 case 0x20C: tmp
= "ITAG12"; break;
248 case 0x20D: tmp
= "ITAG13"; break;
249 case 0x20E: tmp
= "ITAG14"; break;
250 case 0x20F: tmp
= "ITAG15"; break;
251 case 0x300: tmp
= "ILRU"; break;
252 case 0x400: tmp
= "DTAG0"; break;
253 case 0x401: tmp
= "DTAG1"; break;
254 case 0x402: tmp
= "DTAG2"; break;
255 case 0x403: tmp
= "DTAG3"; break;
256 case 0x404: tmp
= "DTAG4"; break;
257 case 0x405: tmp
= "DTAG5"; break;
258 case 0x406: tmp
= "DTAG6"; break;
259 case 0x407: tmp
= "DTAG7"; break;
260 case 0x408: tmp
= "DTAG8"; break;
261 case 0x409: tmp
= "DTAG9"; break;
262 case 0x40A: tmp
= "DTAG10"; break;
263 case 0x40B: tmp
= "DTAG11"; break;
264 case 0x40C: tmp
= "DTAG12"; break;
265 case 0x40D: tmp
= "DTAG13"; break;
266 case 0x40E: tmp
= "DTAG14"; break;
267 case 0x40F: tmp
= "DTAG15"; break;
268 case 0x500: tmp
= "DLRU"; break;
269 case 0x4000: tmp
= "IN0P"; break;
270 case 0x4001: tmp
= "IN1P"; break;
271 case 0x4002: tmp
= "OUTP"; break;
272 default: tmp
= NULL
; break;
276 (*info
-> fprintf_func
) (info
-> stream
, "%s", tmp
);
280 (*info
-> fprintf_func
) (info
-> stream
, "%#lx", value
);
285 if ((value
> 999 || value
< -999)
286 || operand
-> flags
& TIC80_OPERAND_BITFIELD
)
288 (*info
-> fprintf_func
) (info
-> stream
, "%#lx", value
);
292 (*info
-> fprintf_func
) (info
-> stream
, "%ld", value
);
296 /* If this is a scaled operand, then print the modifier */
298 if (R_SCALED (insn
[0], operand
))
300 (*info
-> fprintf_func
) (info
-> stream
, ":s");
303 /* If we printed an open paren before printing this operand, close
304 it now. The flag gets reset on each loop. */
308 (*info
-> fprintf_func
) (info
-> stream
, ")");
This page took 0.03723 seconds and 4 git commands to generate.