/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-2023 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 | 656k | { |
51 | 656k | bfd_byte opbuf[2]; |
52 | 656k | unsigned short opcode; |
53 | 656k | int status, size; |
54 | 656k | const insn_template* tm; |
55 | | |
56 | 656k | status = (*info->read_memory_func) (memaddr, opbuf, 2, info); |
57 | 656k | if (status != 0) |
58 | 53 | { |
59 | 53 | (*info->memory_error_func) (status, memaddr, info); |
60 | 53 | return -1; |
61 | 53 | } |
62 | | |
63 | 656k | opcode = bfd_getl16 (opbuf); |
64 | 656k | tm = tic54x_get_insn (info, memaddr, opcode, &size); |
65 | | |
66 | 656k | info->bytes_per_line = 2; |
67 | 656k | info->bytes_per_chunk = 2; |
68 | 656k | info->octets_per_byte = 2; |
69 | 656k | info->display_endian = BFD_ENDIAN_LITTLE; |
70 | | |
71 | 656k | if (tm->flags & FL_PAR) |
72 | 66.6k | { |
73 | 66.6k | if (!print_parallel_instruction (info, memaddr, opcode, tm, size)) |
74 | 0 | return -1; |
75 | 66.6k | } |
76 | 590k | else |
77 | 590k | { |
78 | 590k | if (!print_instruction (info, memaddr, opcode, |
79 | 590k | (char *) tm->name, |
80 | 590k | tm->operand_types, |
81 | 590k | size, (tm->flags & FL_EXT))) |
82 | 69 | return -1; |
83 | 590k | } |
84 | | |
85 | 656k | return size * 2; |
86 | 656k | } |
87 | | |
88 | | static int |
89 | | has_lkaddr (unsigned short memdata, const insn_template *tm) |
90 | 595k | { |
91 | 595k | return (IS_LKADDR (memdata) |
92 | 595k | && (OPTYPE (tm->operand_types[0]) == OP_Smem |
93 | 80.0k | || OPTYPE (tm->operand_types[1]) == OP_Smem |
94 | 80.0k | || OPTYPE (tm->operand_types[2]) == OP_Smem |
95 | 80.0k | || OPTYPE (tm->operand_types[1]) == OP_Sind |
96 | 80.0k | || OPTYPE (tm->operand_types[0]) == OP_Lmem |
97 | 80.0k | || OPTYPE (tm->operand_types[1]) == OP_Lmem)); |
98 | 595k | } |
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 | 656k | { |
106 | 656k | const insn_template *tm = NULL; |
107 | | |
108 | 67.7M | for (tm = tic54x_optab; tm->name; tm++) |
109 | 67.6M | { |
110 | 67.6M | if (tm->opcode == (memdata & tm->mask)) |
111 | 594k | { |
112 | | /* a few opcodes span two words */ |
113 | 594k | if (tm->flags & FL_EXT) |
114 | 17.5k | { |
115 | | /* if lk addressing is used, the second half of the opcode gets |
116 | | pushed one word later */ |
117 | 17.5k | bfd_byte opbuf[2]; |
118 | 17.5k | bfd_vma addr2 = addr + 1 + has_lkaddr (memdata, tm); |
119 | 17.5k | int status = (*info->read_memory_func) (addr2, opbuf, 2, info); |
120 | | /* FIXME handle errors. */ |
121 | 17.5k | if (status == 0) |
122 | 17.5k | { |
123 | 17.5k | unsigned short data2 = bfd_getl16 (opbuf); |
124 | 17.5k | if (tm->opcode2 == (data2 & tm->mask2)) |
125 | 712 | { |
126 | 712 | if (size) *size = get_insn_size (memdata, tm); |
127 | 712 | return tm; |
128 | 712 | } |
129 | 17.5k | } |
130 | 17.5k | } |
131 | 576k | else |
132 | 576k | { |
133 | 576k | if (size) *size = get_insn_size (memdata, tm); |
134 | 576k | return tm; |
135 | 576k | } |
136 | 594k | } |
137 | 67.6M | } |
138 | 715k | for (tm = (insn_template *) tic54x_paroptab; tm->name; tm++) |
139 | 702k | { |
140 | 702k | if (tm->opcode == (memdata & tm->mask)) |
141 | 66.6k | { |
142 | 66.6k | if (size) *size = get_insn_size (memdata, tm); |
143 | 66.6k | return tm; |
144 | 66.6k | } |
145 | 702k | } |
146 | | |
147 | 12.5k | if (size) *size = 1; |
148 | 12.5k | return &tic54x_unknown_opcode; |
149 | 79.2k | } |
150 | | |
151 | | static int |
152 | | get_insn_size (unsigned short memdata, const insn_template *insn) |
153 | 644k | { |
154 | 644k | int size; |
155 | | |
156 | 644k | if (insn->flags & FL_PAR) |
157 | 66.6k | { |
158 | | /* only non-parallel instructions support lk addressing */ |
159 | 66.6k | size = insn->words; |
160 | 66.6k | } |
161 | 577k | else |
162 | 577k | { |
163 | 577k | size = insn->words + has_lkaddr (memdata, insn); |
164 | 577k | } |
165 | | |
166 | 644k | return size; |
167 | 644k | } |
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 | 723k | { |
178 | 723k | static int n; |
179 | | /* string storage for multiple operands */ |
180 | 723k | char operand[4][64] = { {0},{0},{0},{0}, }; |
181 | 723k | bfd_byte buf[2]; |
182 | 723k | unsigned long opcode2 = 0; |
183 | 723k | unsigned long lkaddr = 0; |
184 | 723k | enum optype src = OP_None; |
185 | 723k | enum optype dst = OP_None; |
186 | 723k | int i, shift; |
187 | 723k | char *comma = ""; |
188 | | |
189 | 723k | info->fprintf_func (info->stream, "%-7s", tm_name); |
190 | | |
191 | 723k | if (size > 1) |
192 | 97.1k | { |
193 | 97.1k | int status = (*info->read_memory_func) (memaddr + 1, buf, 2, info); |
194 | 97.1k | if (status != 0) |
195 | 67 | return 0; |
196 | 97.0k | lkaddr = opcode2 = bfd_getl16 (buf); |
197 | 97.0k | if (size > 2) |
198 | 4.56k | { |
199 | 4.56k | status = (*info->read_memory_func) (memaddr + 2, buf, 2, info); |
200 | 4.56k | if (status != 0) |
201 | 2 | return 0; |
202 | 4.55k | opcode2 = bfd_getl16 (buf); |
203 | 4.55k | } |
204 | 97.0k | } |
205 | | |
206 | 2.28M | for (i = 0; i < MAX_OPERANDS && OPTYPE (tm_operands[i]) != OP_None; i++) |
207 | 1.56M | { |
208 | 1.56M | char *next_comma = ","; |
209 | 1.56M | int optional = (tm_operands[i] & OPT) != 0; |
210 | | |
211 | 1.56M | switch (OPTYPE (tm_operands[i])) |
212 | 1.56M | { |
213 | 154k | case OP_Xmem: |
214 | 154k | sprint_dual_address (info, operand[i], XMEM (opcode)); |
215 | 154k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
216 | 154k | break; |
217 | 109k | case OP_Ymem: |
218 | 109k | sprint_dual_address (info, operand[i], YMEM (opcode)); |
219 | 109k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
220 | 109k | break; |
221 | 365k | case OP_Smem: |
222 | 371k | case OP_Sind: |
223 | 399k | case OP_Lmem: |
224 | 399k | info->fprintf_func (info->stream, "%s", comma); |
225 | 399k | if (INDIRECT (opcode)) |
226 | 99.9k | { |
227 | 99.9k | if (MOD (opcode) >= 12) |
228 | 32.7k | { |
229 | 32.7k | bfd_vma addr = lkaddr; |
230 | 32.7k | int arf = ARF (opcode); |
231 | 32.7k | int mod = MOD (opcode); |
232 | 32.7k | if (mod == 15) |
233 | 13.5k | info->fprintf_func (info->stream, "*("); |
234 | 19.2k | else |
235 | 19.2k | info->fprintf_func (info->stream, "*%sar%d(", |
236 | 19.2k | (mod == 13 || mod == 14 ? "+" : ""), |
237 | 19.2k | arf); |
238 | 32.7k | (*(info->print_address_func)) ((bfd_vma) addr, info); |
239 | 32.7k | info->fprintf_func (info->stream, ")%s", |
240 | 32.7k | mod == 14 ? "%" : ""); |
241 | 32.7k | } |
242 | 67.1k | else |
243 | 67.1k | { |
244 | 67.1k | sprint_indirect_address (info, operand[i], opcode); |
245 | 67.1k | info->fprintf_func (info->stream, "%s", operand[i]); |
246 | 67.1k | } |
247 | 99.9k | } |
248 | 299k | else |
249 | 299k | { |
250 | | /* FIXME -- use labels (print_address_func) */ |
251 | | /* in order to do this, we need to guess what DP is */ |
252 | 299k | sprint_direct_address (info, operand[i], opcode); |
253 | 299k | info->fprintf_func (info->stream, "%s", operand[i]); |
254 | 299k | } |
255 | 399k | break; |
256 | 7.20k | case OP_dmad: |
257 | 7.20k | info->fprintf_func (info->stream, "%s", comma); |
258 | 7.20k | (*(info->print_address_func)) ((bfd_vma) opcode2, info); |
259 | 7.20k | break; |
260 | 8.31k | case OP_xpmad: |
261 | | /* upper 7 bits of address are in the opcode */ |
262 | 8.31k | opcode2 += ((unsigned long) opcode & 0x7F) << 16; |
263 | | /* fall through */ |
264 | 27.1k | case OP_pmad: |
265 | 27.1k | info->fprintf_func (info->stream, "%s", comma); |
266 | 27.1k | (*(info->print_address_func)) ((bfd_vma) opcode2, info); |
267 | 27.1k | break; |
268 | 1.65k | case OP_MMRX: |
269 | 1.65k | sprint_mmr (info, operand[i], MMRX (opcode)); |
270 | 1.65k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
271 | 1.65k | break; |
272 | 1.65k | case OP_MMRY: |
273 | 1.65k | sprint_mmr (info, operand[i], MMRY (opcode)); |
274 | 1.65k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
275 | 1.65k | break; |
276 | 18.5k | case OP_MMR: |
277 | 18.5k | sprint_mmr (info, operand[i], MMR (opcode)); |
278 | 18.5k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
279 | 18.5k | break; |
280 | 4.44k | case OP_PA: |
281 | 4.44k | sprintf (operand[i], "pa%d", (unsigned) opcode2); |
282 | 4.44k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
283 | 4.44k | break; |
284 | 119k | case OP_SRC: |
285 | 119k | src = SRC (ext ? opcode2 : opcode) ? OP_B : OP_A; |
286 | 119k | sprintf (operand[i], (src == OP_B) ? "b" : "a"); |
287 | 119k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
288 | 119k | break; |
289 | 237k | case OP_SRC1: |
290 | 237k | src = SRC1 (ext ? opcode2 : opcode) ? OP_B : OP_A; |
291 | 237k | sprintf (operand[i], (src == OP_B) ? "b" : "a"); |
292 | 237k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
293 | 237k | break; |
294 | 10.0k | case OP_RND: |
295 | 10.0k | dst = DST (opcode) ? OP_B : OP_A; |
296 | 10.0k | sprintf (operand[i], (dst == OP_B) ? "a" : "b"); |
297 | 10.0k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
298 | 10.0k | break; |
299 | 234k | case OP_DST: |
300 | 234k | dst = DST (ext ? opcode2 : opcode) ? OP_B : OP_A; |
301 | 234k | if (!optional || dst != src) |
302 | 202k | { |
303 | 202k | sprintf (operand[i], (dst == OP_B) ? "b" : "a"); |
304 | 202k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
305 | 202k | } |
306 | 31.9k | else |
307 | 31.9k | next_comma = comma; |
308 | 234k | break; |
309 | 6.92k | case OP_B: |
310 | 6.92k | sprintf (operand[i], "b"); |
311 | 6.92k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
312 | 6.92k | break; |
313 | 65 | case OP_A: |
314 | 65 | sprintf (operand[i], "a"); |
315 | 65 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
316 | 65 | break; |
317 | 109 | case OP_ARX: |
318 | 109 | sprintf (operand[i], "ar%d", (int) ARX (opcode)); |
319 | 109 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
320 | 109 | break; |
321 | 9.42k | case OP_SHIFT: |
322 | 9.42k | shift = SHIFT (ext ? opcode2 : opcode); |
323 | 9.42k | if (!optional || shift != 0) |
324 | 8.12k | { |
325 | 8.12k | sprintf (operand[i], "%d", shift); |
326 | 8.12k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
327 | 8.12k | } |
328 | 1.30k | else |
329 | 1.30k | next_comma = comma; |
330 | 9.42k | break; |
331 | 14.9k | case OP_SHFT: |
332 | 14.9k | shift = SHFT (opcode); |
333 | 14.9k | if (!optional || shift != 0) |
334 | 14.3k | { |
335 | 14.3k | sprintf (operand[i], "%d", (unsigned) shift); |
336 | 14.3k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
337 | 14.3k | } |
338 | 602 | else |
339 | 602 | next_comma = comma; |
340 | 14.9k | break; |
341 | 27.6k | case OP_lk: |
342 | 27.6k | sprintf (operand[i], "#%d", (int) (short) opcode2); |
343 | 27.6k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
344 | 27.6k | break; |
345 | 8.31k | case OP_T: |
346 | 8.31k | sprintf (operand[i], "t"); |
347 | 8.31k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
348 | 8.31k | break; |
349 | 14.7k | case OP_TS: |
350 | 14.7k | sprintf (operand[i], "ts"); |
351 | 14.7k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
352 | 14.7k | break; |
353 | 1.43k | case OP_k8: |
354 | 1.43k | sprintf (operand[i], "%d", (int) ((signed char) (opcode & 0xFF))); |
355 | 1.43k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
356 | 1.43k | break; |
357 | 20.6k | case OP_16: |
358 | 20.6k | sprintf (operand[i], "16"); |
359 | 20.6k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
360 | 20.6k | break; |
361 | 8.72k | case OP_ASM: |
362 | 8.72k | sprintf (operand[i], "asm"); |
363 | 8.72k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
364 | 8.72k | break; |
365 | 24.8k | case OP_BITC: |
366 | 24.8k | sprintf (operand[i], "%d", (int) (opcode & 0xF)); |
367 | 24.8k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
368 | 24.8k | break; |
369 | 39.1k | case OP_CC: |
370 | | /* put all CC operands in the same operand */ |
371 | 39.1k | sprint_condition (info, operand[i], opcode); |
372 | 39.1k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
373 | 39.1k | i = MAX_OPERANDS; |
374 | 39.1k | break; |
375 | 6.90k | case OP_CC2: |
376 | 6.90k | sprint_cc2 (info, operand[i], opcode); |
377 | 6.90k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
378 | 6.90k | break; |
379 | 109 | case OP_CC3: |
380 | 109 | { |
381 | 109 | 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 | 109 | sprintf (operand[i], "%s", code[CC3 (opcode)]); |
386 | 109 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
387 | 109 | break; |
388 | 8.31k | } |
389 | 20 | case OP_123: |
390 | 20 | { |
391 | 20 | int code = (opcode >> 8) & 0x3; |
392 | 20 | sprintf (operand[i], "%d", (code == 0) ? 1 : (code == 2) ? 2 : 3); |
393 | 20 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
394 | 20 | break; |
395 | 8.31k | } |
396 | 159 | case OP_k5: |
397 | 159 | sprintf (operand[i], "#%d", ((opcode & 0x1F) ^ 0x10) - 0x10); |
398 | 159 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
399 | 159 | break; |
400 | 4.37k | case OP_k8u: |
401 | 4.37k | sprintf (operand[i], "#%d", (unsigned) (opcode & 0xFF)); |
402 | 4.37k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
403 | 4.37k | break; |
404 | 101 | case OP_k3: |
405 | 101 | sprintf (operand[i], "#%d", (int) (opcode & 0x7)); |
406 | 101 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
407 | 101 | break; |
408 | 1.72k | case OP_lku: |
409 | 1.72k | sprintf (operand[i], "#%d", (unsigned) opcode2); |
410 | 1.72k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
411 | 1.72k | break; |
412 | 486 | case OP_N: |
413 | 486 | n = (opcode >> 9) & 0x1; |
414 | 486 | sprintf (operand[i], "st%d", n); |
415 | 486 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
416 | 486 | break; |
417 | 486 | case OP_SBIT: |
418 | 486 | { |
419 | 486 | const char *status0[] = { |
420 | 486 | "0", "1", "2", "3", "4", "5", "6", "7", "8", |
421 | 486 | "ovb", "ova", "c", "tc", "13", "14", "15" |
422 | 486 | }; |
423 | 486 | const char *status1[] = { |
424 | 486 | "0", "1", "2", "3", "4", |
425 | 486 | "cmpt", "frct", "c16", "sxm", "ovm", "10", |
426 | 486 | "intm", "hm", "xf", "cpl", "braf" |
427 | 486 | }; |
428 | 486 | sprintf (operand[i], "%s", |
429 | 486 | n ? status1[SBIT (opcode)] : status0[SBIT (opcode)]); |
430 | 486 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
431 | 486 | break; |
432 | 8.31k | } |
433 | 31.7k | case OP_12: |
434 | 31.7k | sprintf (operand[i], "%d", (int) ((opcode >> 9) & 1) + 1); |
435 | 31.7k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
436 | 31.7k | break; |
437 | 1.51k | case OP_TRN: |
438 | 1.51k | sprintf (operand[i], "trn"); |
439 | 1.51k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
440 | 1.51k | break; |
441 | 5.78k | case OP_DP: |
442 | 5.78k | sprintf (operand[i], "dp"); |
443 | 5.78k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
444 | 5.78k | break; |
445 | 3.42k | case OP_k9: |
446 | | /* FIXME-- this is DP, print the original address? */ |
447 | 3.42k | sprintf (operand[i], "#%d", (int) (opcode & 0x1FF)); |
448 | 3.42k | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
449 | 3.42k | break; |
450 | 101 | case OP_ARP: |
451 | 101 | sprintf (operand[i], "arp"); |
452 | 101 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
453 | 101 | break; |
454 | 342 | case OP_031: |
455 | 342 | sprintf (operand[i], "%d", (int) (opcode & 0x1F)); |
456 | 342 | info->fprintf_func (info->stream, "%s%s", comma, operand[i]); |
457 | 342 | 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 | 1.56M | } |
463 | 1.56M | comma = next_comma; |
464 | 1.56M | } |
465 | 723k | return 1; |
466 | 723k | } |
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 | 66.6k | { |
475 | 66.6k | print_instruction (info, memaddr, opcode, |
476 | 66.6k | ptm->name, ptm->operand_types, size, 0); |
477 | 66.6k | info->fprintf_func (info->stream, " || "); |
478 | 66.6k | return print_instruction (info, memaddr, opcode, |
479 | 66.6k | ptm->parname, ptm->paroperand_types, size, 0); |
480 | 66.6k | } |
481 | | |
482 | | static int |
483 | | sprint_dual_address (disassemble_info *info ATTRIBUTE_UNUSED, |
484 | | char buf[], |
485 | | unsigned short code) |
486 | 264k | { |
487 | 264k | const char *formats[] = { |
488 | 264k | "*ar%d", |
489 | 264k | "*ar%d-", |
490 | 264k | "*ar%d+", |
491 | 264k | "*ar%d+0%%", |
492 | 264k | }; |
493 | 264k | return sprintf (buf, formats[XMOD (code)], XARX (code)); |
494 | 264k | } |
495 | | |
496 | | static int |
497 | | sprint_indirect_address (disassemble_info *info ATTRIBUTE_UNUSED, |
498 | | char buf[], |
499 | | unsigned short opcode) |
500 | 67.1k | { |
501 | 67.1k | const char *formats[] = { |
502 | 67.1k | "*ar%d", |
503 | 67.1k | "*ar%d-", |
504 | 67.1k | "*ar%d+", |
505 | 67.1k | "*+ar%d", |
506 | 67.1k | "*ar%d-0B", |
507 | 67.1k | "*ar%d-0", |
508 | 67.1k | "*ar%d+0", |
509 | 67.1k | "*ar%d+0B", |
510 | 67.1k | "*ar%d-%%", |
511 | 67.1k | "*ar%d-0%%", |
512 | 67.1k | "*ar%d+%%", |
513 | 67.1k | "*ar%d+0%%", |
514 | 67.1k | }; |
515 | 67.1k | return sprintf (buf, formats[MOD (opcode)], ARF (opcode)); |
516 | 67.1k | } |
517 | | |
518 | | static int |
519 | | sprint_direct_address (disassemble_info *info ATTRIBUTE_UNUSED, |
520 | | char buf[], |
521 | | unsigned short opcode) |
522 | 299k | { |
523 | | /* FIXME -- look up relocation if available */ |
524 | 299k | return sprintf (buf, "DP+0x%02x", (int) (opcode & 0x7F)); |
525 | 299k | } |
526 | | |
527 | | static int |
528 | | sprint_mmr (disassemble_info *info ATTRIBUTE_UNUSED, |
529 | | char buf[], |
530 | | int mmr) |
531 | 21.8k | { |
532 | 21.8k | const tic54x_symbol *reg = tic54x_mmregs; |
533 | 1.89M | while (reg->name != NULL) |
534 | 1.87M | { |
535 | 1.87M | if (mmr == reg->value) |
536 | 10.9k | { |
537 | 10.9k | sprintf (buf, "%s", (reg + 1)->name); |
538 | 10.9k | return 1; |
539 | 10.9k | } |
540 | 1.86M | ++reg; |
541 | 1.86M | } |
542 | 10.8k | sprintf (buf, "MMR(%d)", mmr); /* FIXME -- different targets. */ |
543 | 10.8k | return 0; |
544 | 21.8k | } |
545 | | |
546 | | static int |
547 | | sprint_cc2 (disassemble_info *info ATTRIBUTE_UNUSED, |
548 | | char *buf, |
549 | | unsigned short opcode) |
550 | 6.90k | { |
551 | 6.90k | const char *cc2[] = { |
552 | 6.90k | "??", "??", "ageq", "alt", "aneq", "aeq", "agt", "aleq", |
553 | 6.90k | "??", "??", "bgeq", "blt", "bneq", "beq", "bgt", "bleq", |
554 | 6.90k | }; |
555 | 6.90k | return sprintf (buf, "%s", cc2[opcode & 0xF]); |
556 | 6.90k | } |
557 | | |
558 | | static int |
559 | | sprint_condition (disassemble_info *info ATTRIBUTE_UNUSED, |
560 | | char *buf, |
561 | | unsigned short opcode) |
562 | 39.1k | { |
563 | 39.1k | char *start = buf; |
564 | 39.1k | const char *cmp[] = { |
565 | 39.1k | "??", "??", "geq", "lt", "neq", "eq", "gt", "leq" |
566 | 39.1k | }; |
567 | 39.1k | if (opcode & 0x40) |
568 | 28.1k | { |
569 | 28.1k | char acc = (opcode & 0x8) ? 'b' : 'a'; |
570 | 28.1k | if (opcode & 0x7) |
571 | 26.9k | buf += sprintf (buf, "%c%s%s", acc, cmp[(opcode & 0x7)], |
572 | 26.9k | (opcode & 0x20) ? ", " : ""); |
573 | 28.1k | if (opcode & 0x20) |
574 | 24.9k | buf += sprintf (buf, "%c%s", acc, (opcode & 0x10) ? "ov" : "nov"); |
575 | 28.1k | } |
576 | 10.9k | else if (opcode & 0x3F) |
577 | 7.73k | { |
578 | 7.73k | if (opcode & 0x30) |
579 | 4.85k | buf += sprintf (buf, "%s%s", |
580 | 4.85k | ((opcode & 0x30) == 0x30) ? "tc" : "ntc", |
581 | 4.85k | (opcode & 0x0F) ? ", " : ""); |
582 | 7.73k | if (opcode & 0x0C) |
583 | 5.60k | buf += sprintf (buf, "%s%s", |
584 | 5.60k | ((opcode & 0x0C) == 0x0C) ? "c" : "nc", |
585 | 5.60k | (opcode & 0x03) ? ", " : ""); |
586 | 7.73k | if (opcode & 0x03) |
587 | 5.93k | buf += sprintf (buf, "%s", |
588 | 5.93k | ((opcode & 0x03) == 0x03) ? "bio" : "nbio"); |
589 | 7.73k | } |
590 | 3.25k | else |
591 | 3.25k | buf += sprintf (buf, "unc"); |
592 | | |
593 | 39.1k | return buf - start; |
594 | 39.1k | } |