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