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