/src/binutils-gdb/opcodes/tic54x-dis.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Disassembly routines for TMS320C54X architecture |
2 | | Copyright (C) 1999-2025 Free Software Foundation, Inc. |
3 | | Contributed by Timothy Wall (twall@cygnus.com) |
4 | | |
5 | | This file is part of the GNU opcodes library. |
6 | | |
7 | | This library is free software; you can redistribute it and/or modify |
8 | | it under the terms of the GNU General Public License as published by |
9 | | the Free Software Foundation; either version 3, or (at your option) |
10 | | any later version. |
11 | | |
12 | | It is distributed in the hope that it will be useful, but WITHOUT |
13 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
14 | | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
15 | | License for more details. |
16 | | |
17 | | You should have received a copy of the GNU General Public License |
18 | | along with this file; see the file COPYING. If not, write to the |
19 | | Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, |
20 | | MA 02110-1301, USA. */ |
21 | | |
22 | | #include "sysdep.h" |
23 | | #include <errno.h> |
24 | | #include <math.h> |
25 | | #include <stdlib.h> |
26 | | #include "disassemble.h" |
27 | | #include "opcode/tic54x.h" |
28 | | #include "coff/tic54x.h" |
29 | | |
30 | | static int has_lkaddr (unsigned short, const insn_template *); |
31 | | static int get_insn_size (unsigned short, const insn_template *); |
32 | | static int print_instruction (disassemble_info *, bfd_vma, |
33 | | unsigned short, const char *, |
34 | | const enum optype [], int, int); |
35 | | static int print_parallel_instruction (disassemble_info *, bfd_vma, |
36 | | unsigned short, |
37 | | const insn_template *, int); |
38 | | static int sprint_dual_address (disassemble_info *,char [], |
39 | | unsigned short); |
40 | | static int sprint_indirect_address (disassemble_info *,char [], |
41 | | unsigned short); |
42 | | static int sprint_direct_address (disassemble_info *,char [], |
43 | | unsigned short); |
44 | | static int sprint_mmr (disassemble_info *,char [],int); |
45 | | static int sprint_condition (disassemble_info *,char *,unsigned short); |
46 | | static int sprint_cc2 (disassemble_info *,char *,unsigned short); |
47 | | |
48 | | int |
49 | | print_insn_tic54x (bfd_vma memaddr, disassemble_info *info) |
50 | 7.77M | { |
51 | 7.77M | bfd_byte opbuf[2]; |
52 | 7.77M | unsigned short opcode; |
53 | 7.77M | int status, size; |
54 | 7.77M | const insn_template* tm; |
55 | | |
56 | 7.77M | status = (*info->read_memory_func) (memaddr, opbuf, 2, info); |
57 | 7.77M | if (status != 0) |
58 | 195 | { |
59 | 195 | (*info->memory_error_func) (status, memaddr, info); |
60 | 195 | return -1; |
61 | 195 | } |
62 | | |
63 | 7.77M | opcode = bfd_getl16 (opbuf); |
64 | 7.77M | tm = tic54x_get_insn (info, memaddr, opcode, &size); |
65 | | |
66 | 7.77M | info->bytes_per_line = 2; |
67 | 7.77M | info->bytes_per_chunk = 2; |
68 | 7.77M | info->octets_per_byte = 2; |
69 | 7.77M | info->display_endian = BFD_ENDIAN_LITTLE; |
70 | | |
71 | 7.77M | if (tm->flags & FL_PAR) |
72 | 393k | { |
73 | 393k | if (!print_parallel_instruction (info, memaddr, opcode, tm, size)) |
74 | 0 | return -1; |
75 | 393k | } |
76 | 7.38M | else |
77 | 7.38M | { |
78 | 7.38M | if (!print_instruction (info, memaddr, opcode, |
79 | 7.38M | (char *) tm->name, |
80 | 7.38M | tm->operand_types, |
81 | 7.38M | size, (tm->flags & FL_EXT))) |
82 | 212 | return -1; |
83 | 7.38M | } |
84 | | |
85 | 7.77M | return size * 2; |
86 | 7.77M | } |
87 | | |
88 | | static int |
89 | | has_lkaddr (unsigned short memdata, const insn_template *tm) |
90 | 7.44M | { |
91 | 7.44M | return (IS_LKADDR (memdata) |
92 | 7.44M | && (OPTYPE (tm->operand_types[0]) == OP_Smem |
93 | 849k | || OPTYPE (tm->operand_types[1]) == OP_Smem |
94 | 849k | || OPTYPE (tm->operand_types[2]) == OP_Smem |
95 | 849k | || OPTYPE (tm->operand_types[1]) == OP_Sind |
96 | 849k | || OPTYPE (tm->operand_types[0]) == OP_Lmem |
97 | 849k | || OPTYPE (tm->operand_types[1]) == OP_Lmem)); |
98 | 7.44M | } |
99 | | |
100 | | /* always returns 1 (whether an insn template was found) since we provide an |
101 | | "unknown instruction" template */ |
102 | | const insn_template* |
103 | | tic54x_get_insn (disassemble_info *info, bfd_vma addr, |
104 | | unsigned short memdata, int *size) |
105 | 7.77M | { |
106 | 7.77M | const insn_template *tm = NULL; |
107 | | |
108 | 693M | for (tm = tic54x_optab; tm->name; tm++) |
109 | 693M | { |
110 | 693M | if (tm->opcode == (memdata & tm->mask)) |
111 | 7.44M | { |
112 | | /* a few opcodes span two words */ |
113 | 7.44M | if (tm->flags & FL_EXT) |
114 | 131k | { |
115 | | /* if lk addressing is used, the second half of the opcode gets |
116 | | pushed one word later */ |
117 | 131k | bfd_byte opbuf[2]; |
118 | 131k | bfd_vma addr2 = addr + 1 + has_lkaddr (memdata, tm); |
119 | 131k | int status = (*info->read_memory_func) (addr2, opbuf, 2, info); |
120 | | /* FIXME handle errors. */ |
121 | 131k | if (status == 0) |
122 | 131k | { |
123 | 131k | unsigned short data2 = bfd_getl16 (opbuf); |
124 | 131k | if (tm->opcode2 == (data2 & tm->mask2)) |
125 | 930 | { |
126 | 930 | if (size) *size = get_insn_size (memdata, tm); |
127 | 930 | return tm; |
128 | 930 | } |
129 | 131k | } |
130 | 131k | } |
131 | 7.30M | else |
132 | 7.30M | { |
133 | 7.30M | if (size) *size = get_insn_size (memdata, tm); |
134 | 7.30M | return tm; |
135 | 7.30M | } |
136 | 7.44M | } |
137 | 693M | } |
138 | 4.03M | for (tm = (insn_template *) tic54x_paroptab; tm->name; tm++) |
139 | 3.96M | { |
140 | 3.96M | if (tm->opcode == (memdata & tm->mask)) |
141 | 393k | { |
142 | 393k | if (size) *size = get_insn_size (memdata, tm); |
143 | 393k | return tm; |
144 | 393k | } |
145 | 3.96M | } |
146 | | |
147 | 70.1k | if (size) *size = 1; |
148 | 70.1k | return &tic54x_unknown_opcode; |
149 | 463k | } |
150 | | |
151 | | static int |
152 | | get_insn_size (unsigned short memdata, const insn_template *insn) |
153 | 7.70M | { |
154 | 7.70M | int size; |
155 | | |
156 | 7.70M | if (insn->flags & FL_PAR) |
157 | 393k | { |
158 | | /* only non-parallel instructions support lk addressing */ |
159 | 393k | size = insn->words; |
160 | 393k | } |
161 | 7.31M | else |
162 | 7.31M | { |
163 | 7.31M | size = insn->words + has_lkaddr (memdata, insn); |
164 | 7.31M | } |
165 | | |
166 | 7.70M | return size; |
167 | 7.70M | } |
168 | | |
169 | | int |
170 | | print_instruction (disassemble_info *info, |
171 | | bfd_vma memaddr, |
172 | | unsigned short opcode, |
173 | | const char *tm_name, |
174 | | const enum optype tm_operands[], |
175 | | int size, |
176 | | int ext) |
177 | 8.16M | { |
178 | 8.16M | static int n; |
179 | | /* string storage for multiple operands */ |
180 | 8.16M | char operand[4][64] = { {0},{0},{0},{0}, }; |
181 | 8.16M | bfd_byte buf[2]; |
182 | 8.16M | unsigned long opcode2 = 0; |
183 | 8.16M | unsigned long lkaddr = 0; |
184 | 8.16M | enum optype src = OP_None; |
185 | 8.16M | enum optype dst = OP_None; |
186 | 8.16M | int i, shift; |
187 | 8.16M | char *comma = ""; |
188 | | |
189 | 8.16M | info->fprintf_func (info->stream, "%-7s", tm_name); |
190 | | |
191 | 8.16M | if (size > 1) |
192 | 1.08M | { |
193 | 1.08M | int status = (*info->read_memory_func) (memaddr + 1, buf, 2, info); |
194 | 1.08M | if (status != 0) |
195 | 204 | return 0; |
196 | 1.08M | lkaddr = opcode2 = bfd_getl16 (buf); |
197 | 1.08M | if (size > 2) |
198 | 28.3k | { |
199 | 28.3k | status = (*info->read_memory_func) (memaddr + 2, buf, 2, info); |
200 | 28.3k | if (status != 0) |
201 | 8 | return 0; |
202 | 28.3k | opcode2 = bfd_getl16 (buf); |
203 | 28.3k | } |
204 | 1.08M | } |
205 | | |
206 | 25.5M | for (i = 0; i < MAX_OPERANDS && OPTYPE (tm_operands[i]) != OP_None; i++) |
207 | 17.4M | { |
208 | 17.4M | char *next_comma = ","; |
209 | 17.4M | int optional = (tm_operands[i] & OPT) != 0; |
210 | | |
211 | 17.4M | switch (OPTYPE (tm_operands[i])) |
212 | 17.4M | { |
213 | 892k | case OP_Xmem: |
214 | 892k | sprint_dual_address (info, operand[i], XMEM (opcode)); |
215 | 892k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
216 | 892k | break; |
217 | 713k | case OP_Ymem: |
218 | 713k | sprint_dual_address (info, operand[i], YMEM (opcode)); |
219 | 713k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
220 | 713k | break; |
221 | 5.33M | case OP_Smem: |
222 | 5.38M | case OP_Sind: |
223 | 5.64M | case OP_Lmem: |
224 | 5.64M | info->fprintf_func (info->stream, "%s", comma); |
225 | 5.64M | if (INDIRECT (opcode)) |
226 | 913k | { |
227 | 913k | if (MOD (opcode) >= 12) |
228 | 345k | { |
229 | 345k | bfd_vma addr = lkaddr; |
230 | 345k | int arf = ARF (opcode); |
231 | 345k | int mod = MOD (opcode); |
232 | 345k | if (mod == 15) |
233 | 141k | info->fprintf_func (info->stream, "*("); |
234 | 203k | else |
235 | 203k | info->fprintf_func (info->stream, "*%sar%d(", |
236 | 203k | (mod == 13 || mod == 14 ? "+" : ""), |
237 | 203k | arf); |
238 | 345k | (*(info->print_address_func)) ((bfd_vma) addr, info); |
239 | 345k | info->fprintf_func (info->stream, ")%s", |
240 | 345k | mod == 14 ? "%" : ""); |
241 | 345k | } |
242 | 568k | else |
243 | 568k | { |
244 | 568k | sprint_indirect_address (info, operand[i], opcode); |
245 | 568k | info->fprintf_func (info->stream, "%s", operand[i]); |
246 | 568k | } |
247 | 913k | } |
248 | 4.73M | else |
249 | 4.73M | { |
250 | | /* FIXME -- use labels (print_address_func) */ |
251 | | /* in order to do this, we need to guess what DP is */ |
252 | 4.73M | sprint_direct_address (info, operand[i], opcode); |
253 | 4.73M | info->fprintf_func (info->stream, "%s", operand[i]); |
254 | 4.73M | } |
255 | 5.64M | break; |
256 | 121k | case OP_dmad: |
257 | 121k | info->fprintf_func (info->stream, "%s", comma); |
258 | 121k | (*(info->print_address_func)) ((bfd_vma) opcode2, info); |
259 | 121k | break; |
260 | 39.4k | case OP_xpmad: |
261 | | /* upper 7 bits of address are in the opcode */ |
262 | 39.4k | opcode2 += ((unsigned long) opcode & 0x7F) << 16; |
263 | | /* fall through */ |
264 | 194k | case OP_pmad: |
265 | 194k | info->fprintf_func (info->stream, "%s", comma); |
266 | 194k | (*(info->print_address_func)) ((bfd_vma) opcode2, info); |
267 | 194k | break; |
268 | 13.1k | case OP_MMRX: |
269 | 13.1k | sprint_mmr (info, operand[i], MMRX (opcode)); |
270 | 13.1k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
271 | 13.1k | break; |
272 | 13.1k | case OP_MMRY: |
273 | 13.1k | sprint_mmr (info, operand[i], MMRY (opcode)); |
274 | 13.1k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
275 | 13.1k | break; |
276 | 403k | case OP_MMR: |
277 | 403k | sprint_mmr (info, operand[i], MMR (opcode)); |
278 | 403k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
279 | 403k | break; |
280 | 76.0k | case OP_PA: |
281 | 76.0k | sprintf (operand[i], "pa%d", (unsigned) opcode2); |
282 | 76.0k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
283 | 76.0k | break; |
284 | 912k | case OP_SRC: |
285 | 912k | src = SRC (ext ? opcode2 : opcode) ? OP_B : OP_A; |
286 | 912k | sprintf (operand[i], (src == OP_B) ? "b" : "a"); |
287 | 912k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
288 | 912k | break; |
289 | 3.99M | case OP_SRC1: |
290 | 3.99M | src = SRC1 (ext ? opcode2 : opcode) ? OP_B : OP_A; |
291 | 3.99M | sprintf (operand[i], (src == OP_B) ? "b" : "a"); |
292 | 3.99M | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
293 | 3.99M | break; |
294 | 70.2k | case OP_RND: |
295 | 70.2k | dst = DST (opcode) ? OP_B : OP_A; |
296 | 70.2k | sprintf (operand[i], (dst == OP_B) ? "a" : "b"); |
297 | 70.2k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
298 | 70.2k | break; |
299 | 2.00M | case OP_DST: |
300 | 2.00M | dst = DST (ext ? opcode2 : opcode) ? OP_B : OP_A; |
301 | 2.00M | if (!optional || dst != src) |
302 | 1.70M | { |
303 | 1.70M | sprintf (operand[i], (dst == OP_B) ? "b" : "a"); |
304 | 1.70M | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
305 | 1.70M | } |
306 | 301k | else |
307 | 301k | next_comma = comma; |
308 | 2.00M | break; |
309 | 74.8k | case OP_B: |
310 | 74.8k | sprintf (operand[i], "b"); |
311 | 74.8k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
312 | 74.8k | break; |
313 | 840 | case OP_A: |
314 | 840 | sprintf (operand[i], "a"); |
315 | 840 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
316 | 840 | break; |
317 | 1.43k | case OP_ARX: |
318 | 1.43k | sprintf (operand[i], "ar%d", (int) ARX (opcode)); |
319 | 1.43k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
320 | 1.43k | break; |
321 | 51.1k | case OP_SHIFT: |
322 | 51.1k | shift = SHIFT (ext ? opcode2 : opcode); |
323 | 51.1k | if (!optional || shift != 0) |
324 | 41.6k | { |
325 | 41.6k | sprintf (operand[i], "%d", shift); |
326 | 41.6k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
327 | 41.6k | } |
328 | 9.50k | else |
329 | 9.50k | next_comma = comma; |
330 | 51.1k | break; |
331 | 115k | case OP_SHFT: |
332 | 115k | shift = SHFT (opcode); |
333 | 115k | if (!optional || shift != 0) |
334 | 114k | { |
335 | 114k | sprintf (operand[i], "%d", (unsigned) shift); |
336 | 114k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
337 | 114k | } |
338 | 1.30k | else |
339 | 1.30k | next_comma = comma; |
340 | 115k | break; |
341 | 365k | case OP_lk: |
342 | 365k | sprintf (operand[i], "#%d", (int) (short) opcode2); |
343 | 365k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
344 | 365k | break; |
345 | 81.2k | case OP_T: |
346 | 81.2k | sprintf (operand[i], "t"); |
347 | 81.2k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
348 | 81.2k | break; |
349 | 166k | case OP_TS: |
350 | 166k | sprintf (operand[i], "ts"); |
351 | 166k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
352 | 166k | break; |
353 | 10.4k | case OP_k8: |
354 | 10.4k | sprintf (operand[i], "%d", (int) ((signed char) (opcode & 0xFF))); |
355 | 10.4k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
356 | 10.4k | break; |
357 | 192k | case OP_16: |
358 | 192k | sprintf (operand[i], "16"); |
359 | 192k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
360 | 192k | break; |
361 | 91.4k | case OP_ASM: |
362 | 91.4k | sprintf (operand[i], "asm"); |
363 | 91.4k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
364 | 91.4k | break; |
365 | 12.9k | case OP_BITC: |
366 | 12.9k | sprintf (operand[i], "%d", (int) (opcode & 0xF)); |
367 | 12.9k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
368 | 12.9k | break; |
369 | 482k | case OP_CC: |
370 | | /* put all CC operands in the same operand */ |
371 | 482k | sprint_condition (info, operand[i], opcode); |
372 | 482k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
373 | 482k | i = MAX_OPERANDS; |
374 | 482k | break; |
375 | 57.3k | case OP_CC2: |
376 | 57.3k | sprint_cc2 (info, operand[i], opcode); |
377 | 57.3k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
378 | 57.3k | break; |
379 | 1.43k | case OP_CC3: |
380 | 1.43k | { |
381 | 1.43k | const char *code[] = { "eq", "lt", "gt", "neq" }; |
382 | | |
383 | | /* Do not use sprintf with only two parameters as a |
384 | | compiler warning could be generated in such conditions. */ |
385 | 1.43k | sprintf (operand[i], "%s", code[CC3 (opcode)]); |
386 | 1.43k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
387 | 1.43k | break; |
388 | 39.4k | } |
389 | 104 | case OP_123: |
390 | 104 | { |
391 | 104 | int code = (opcode >> 8) & 0x3; |
392 | 104 | sprintf (operand[i], "%d", (code == 0) ? 1 : (code == 2) ? 2 : 3); |
393 | 104 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
394 | 104 | break; |
395 | 39.4k | } |
396 | 1.51k | case OP_k5: |
397 | 1.51k | sprintf (operand[i], "#%d", ((opcode & 0x1F) ^ 0x10) - 0x10); |
398 | 1.51k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
399 | 1.51k | break; |
400 | 88.9k | case OP_k8u: |
401 | 88.9k | sprintf (operand[i], "#%d", (unsigned) (opcode & 0xFF)); |
402 | 88.9k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
403 | 88.9k | break; |
404 | 69 | case OP_k3: |
405 | 69 | sprintf (operand[i], "#%d", (int) (opcode & 0x7)); |
406 | 69 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
407 | 69 | break; |
408 | 9.80k | case OP_lku: |
409 | 9.80k | sprintf (operand[i], "#%d", (unsigned) opcode2); |
410 | 9.80k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
411 | 9.80k | break; |
412 | 2.38k | case OP_N: |
413 | 2.38k | n = (opcode >> 9) & 0x1; |
414 | 2.38k | sprintf (operand[i], "st%d", n); |
415 | 2.38k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
416 | 2.38k | break; |
417 | 2.38k | case OP_SBIT: |
418 | 2.38k | { |
419 | 2.38k | const char *status0[] = { |
420 | 2.38k | "0", "1", "2", "3", "4", "5", "6", "7", "8", |
421 | 2.38k | "ovb", "ova", "c", "tc", "13", "14", "15" |
422 | 2.38k | }; |
423 | 2.38k | const char *status1[] = { |
424 | 2.38k | "0", "1", "2", "3", "4", |
425 | 2.38k | "cmpt", "frct", "c16", "sxm", "ovm", "10", |
426 | 2.38k | "intm", "hm", "xf", "cpl", "braf" |
427 | 2.38k | }; |
428 | 2.38k | sprintf (operand[i], "%s", |
429 | 2.38k | n ? status1[SBIT (opcode)] : status0[SBIT (opcode)]); |
430 | 2.38k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
431 | 2.38k | break; |
432 | 39.4k | } |
433 | 432k | case OP_12: |
434 | 432k | sprintf (operand[i], "%d", (int) ((opcode >> 9) & 1) + 1); |
435 | 432k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
436 | 432k | break; |
437 | 23.5k | case OP_TRN: |
438 | 23.5k | sprintf (operand[i], "trn"); |
439 | 23.5k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
440 | 23.5k | break; |
441 | 55.0k | case OP_DP: |
442 | 55.0k | sprintf (operand[i], "dp"); |
443 | 55.0k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
444 | 55.0k | break; |
445 | 40.9k | case OP_k9: |
446 | | /* FIXME-- this is DP, print the original address? */ |
447 | 40.9k | sprintf (operand[i], "#%d", (int) (opcode & 0x1FF)); |
448 | 40.9k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
449 | 40.9k | break; |
450 | 69 | case OP_ARP: |
451 | 69 | sprintf (operand[i], "arp"); |
452 | 69 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
453 | 69 | break; |
454 | 909 | case OP_031: |
455 | 909 | sprintf (operand[i], "%d", (int) (opcode & 0x1F)); |
456 | 909 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
457 | 909 | break; |
458 | 0 | default: |
459 | 0 | sprintf (operand[i], "??? (0x%x)", tm_operands[i]); |
460 | 0 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
461 | 0 | break; |
462 | 17.4M | } |
463 | 17.4M | comma = next_comma; |
464 | 17.4M | } |
465 | 8.16M | return 1; |
466 | 8.16M | } |
467 | | |
468 | | static int |
469 | | print_parallel_instruction (disassemble_info *info, |
470 | | bfd_vma memaddr, |
471 | | unsigned short opcode, |
472 | | const insn_template *ptm, |
473 | | int size) |
474 | 393k | { |
475 | 393k | print_instruction (info, memaddr, opcode, |
476 | 393k | ptm->name, ptm->operand_types, size, 0); |
477 | 393k | info->fprintf_func (info->stream, " || "); |
478 | 393k | return print_instruction (info, memaddr, opcode, |
479 | 393k | ptm->parname, ptm->paroperand_types, size, 0); |
480 | 393k | } |
481 | | |
482 | | static int |
483 | | sprint_dual_address (disassemble_info *info ATTRIBUTE_UNUSED, |
484 | | char buf[], |
485 | | unsigned short code) |
486 | 1.60M | { |
487 | 1.60M | const char *formats[] = { |
488 | 1.60M | "*ar%d", |
489 | 1.60M | "*ar%d-", |
490 | 1.60M | "*ar%d+", |
491 | 1.60M | "*ar%d+0%%", |
492 | 1.60M | }; |
493 | 1.60M | return sprintf (buf, formats[XMOD (code)], XARX (code)); |
494 | 1.60M | } |
495 | | |
496 | | static int |
497 | | sprint_indirect_address (disassemble_info *info ATTRIBUTE_UNUSED, |
498 | | char buf[], |
499 | | unsigned short opcode) |
500 | 568k | { |
501 | 568k | const char *formats[] = { |
502 | 568k | "*ar%d", |
503 | 568k | "*ar%d-", |
504 | 568k | "*ar%d+", |
505 | 568k | "*+ar%d", |
506 | 568k | "*ar%d-0B", |
507 | 568k | "*ar%d-0", |
508 | 568k | "*ar%d+0", |
509 | 568k | "*ar%d+0B", |
510 | 568k | "*ar%d-%%", |
511 | 568k | "*ar%d-0%%", |
512 | 568k | "*ar%d+%%", |
513 | 568k | "*ar%d+0%%", |
514 | 568k | }; |
515 | 568k | return sprintf (buf, formats[MOD (opcode)], ARF (opcode)); |
516 | 568k | } |
517 | | |
518 | | static int |
519 | | sprint_direct_address (disassemble_info *info ATTRIBUTE_UNUSED, |
520 | | char buf[], |
521 | | unsigned short opcode) |
522 | 4.73M | { |
523 | | /* FIXME -- look up relocation if available */ |
524 | 4.73M | return sprintf (buf, "DP+0x%02x", (int) (opcode & 0x7F)); |
525 | 4.73M | } |
526 | | |
527 | | static int |
528 | | sprint_mmr (disassemble_info *info ATTRIBUTE_UNUSED, |
529 | | char buf[], |
530 | | int mmr) |
531 | 429k | { |
532 | 429k | const tic54x_symbol *reg = tic54x_mmregs; |
533 | 35.4M | while (reg->name != NULL) |
534 | 35.2M | { |
535 | 35.2M | if (mmr == reg->value) |
536 | 200k | { |
537 | 200k | sprintf (buf, "%s", (reg + 1)->name); |
538 | 200k | return 1; |
539 | 200k | } |
540 | 35.0M | ++reg; |
541 | 35.0M | } |
542 | 229k | sprintf (buf, "MMR(%d)", mmr); /* FIXME -- different targets. */ |
543 | 229k | return 0; |
544 | 429k | } |
545 | | |
546 | | static int |
547 | | sprint_cc2 (disassemble_info *info ATTRIBUTE_UNUSED, |
548 | | char *buf, |
549 | | unsigned short opcode) |
550 | 57.3k | { |
551 | 57.3k | const char *cc2[] = { |
552 | 57.3k | "??", "??", "ageq", "alt", "aneq", "aeq", "agt", "aleq", |
553 | 57.3k | "??", "??", "bgeq", "blt", "bneq", "beq", "bgt", "bleq", |
554 | 57.3k | }; |
555 | 57.3k | return sprintf (buf, "%s", cc2[opcode & 0xF]); |
556 | 57.3k | } |
557 | | |
558 | | static int |
559 | | sprint_condition (disassemble_info *info ATTRIBUTE_UNUSED, |
560 | | char *buf, |
561 | | unsigned short opcode) |
562 | 482k | { |
563 | 482k | char *start = buf; |
564 | 482k | const char *cmp[] = { |
565 | 482k | "??", "??", "geq", "lt", "neq", "eq", "gt", "leq" |
566 | 482k | }; |
567 | 482k | if (opcode & 0x40) |
568 | 360k | { |
569 | 360k | char acc = (opcode & 0x8) ? 'b' : 'a'; |
570 | 360k | if (opcode & 0x7) |
571 | 351k | buf += sprintf (buf, "%c%s%s", acc, cmp[(opcode & 0x7)], |
572 | 351k | (opcode & 0x20) ? ", " : ""); |
573 | 360k | if (opcode & 0x20) |
574 | 339k | buf += sprintf (buf, "%c%s", acc, (opcode & 0x10) ? "ov" : "nov"); |
575 | 360k | } |
576 | 122k | else if (opcode & 0x3F) |
577 | 62.5k | { |
578 | 62.5k | if (opcode & 0x30) |
579 | 37.8k | buf += sprintf (buf, "%s%s", |
580 | 37.8k | ((opcode & 0x30) == 0x30) ? "tc" : "ntc", |
581 | 37.8k | (opcode & 0x0F) ? ", " : ""); |
582 | 62.5k | if (opcode & 0x0C) |
583 | 39.0k | buf += sprintf (buf, "%s%s", |
584 | 39.0k | ((opcode & 0x0C) == 0x0C) ? "c" : "nc", |
585 | 39.0k | (opcode & 0x03) ? ", " : ""); |
586 | 62.5k | if (opcode & 0x03) |
587 | 47.4k | buf += sprintf (buf, "%s", |
588 | 47.4k | ((opcode & 0x03) == 0x03) ? "bio" : "nbio"); |
589 | 62.5k | } |
590 | 59.9k | else |
591 | 59.9k | buf += sprintf (buf, "unc"); |
592 | | |
593 | 482k | return buf - start; |
594 | 482k | } |