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