00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <errno.h>
00021 #include <math.h>
00022 #include <stdlib.h>
00023 #include "sysdep.h"
00024 #include "dis-asm.h"
00025 #include "opcode/tic54x.h"
00026 #include "coff/tic54x.h"
00027
00028 static int has_lkaddr (unsigned short, const template *);
00029 static int get_insn_size (unsigned short, const template *);
00030 static int print_instruction (disassemble_info *, bfd_vma,
00031 unsigned short, const char *,
00032 const enum optype [], int, int);
00033 static int print_parallel_instruction (disassemble_info *, bfd_vma,
00034 unsigned short,
00035 const template *, int);
00036 static int sprint_dual_address (disassemble_info *,char [],
00037 unsigned short);
00038 static int sprint_indirect_address (disassemble_info *,char [],
00039 unsigned short);
00040 static int sprint_direct_address (disassemble_info *,char [],
00041 unsigned short);
00042 static int sprint_mmr (disassemble_info *,char [],int);
00043 static int sprint_condition (disassemble_info *,char *,unsigned short);
00044 static int sprint_cc2 (disassemble_info *,char *,unsigned short);
00045
00046 int
00047 print_insn_tic54x (bfd_vma memaddr, disassemble_info *info)
00048 {
00049 bfd_byte opbuf[2];
00050 unsigned short opcode;
00051 int status, size;
00052 const template* tm;
00053
00054 status = (*info->read_memory_func) (memaddr, opbuf, 2, info);
00055 if (status != 0)
00056 {
00057 (*info->memory_error_func) (status, memaddr, info);
00058 return -1;
00059 }
00060
00061 opcode = bfd_getl16 (opbuf);
00062 tm = tic54x_get_insn (info, memaddr, opcode, &size);
00063
00064 info->bytes_per_line = 2;
00065 info->bytes_per_chunk = 2;
00066 info->octets_per_byte = 2;
00067 info->display_endian = BFD_ENDIAN_LITTLE;
00068
00069 if (tm->flags & FL_PAR)
00070 {
00071 if (!print_parallel_instruction (info, memaddr, opcode, tm, size))
00072 return -1;
00073 }
00074 else
00075 {
00076 if (!print_instruction (info, memaddr, opcode,
00077 (char *) tm->name,
00078 tm->operand_types,
00079 size, (tm->flags & FL_EXT)))
00080 return -1;
00081 }
00082
00083 return size * 2;
00084 }
00085
00086 static int
00087 has_lkaddr (unsigned short memdata, const template *tm)
00088 {
00089 return (IS_LKADDR (memdata)
00090 && (OPTYPE (tm->operand_types[0]) == OP_Smem
00091 || OPTYPE (tm->operand_types[1]) == OP_Smem
00092 || OPTYPE (tm->operand_types[2]) == OP_Smem
00093 || OPTYPE (tm->operand_types[1]) == OP_Sind
00094 || OPTYPE (tm->operand_types[0]) == OP_Lmem
00095 || OPTYPE (tm->operand_types[1]) == OP_Lmem));
00096 }
00097
00098
00099
00100 const template*
00101 tic54x_get_insn (disassemble_info *info, bfd_vma addr,
00102 unsigned short memdata, int *size)
00103 {
00104 const template *tm = NULL;
00105
00106 for (tm = tic54x_optab; tm->name; tm++)
00107 {
00108 if (tm->opcode == (memdata & tm->mask))
00109 {
00110
00111 if (tm->flags & FL_EXT)
00112 {
00113
00114
00115 bfd_byte opbuf[2];
00116 bfd_vma addr2 = addr + 1 + has_lkaddr (memdata, tm);
00117 int status = (*info->read_memory_func) (addr2, opbuf, 2, info);
00118
00119 if (status == 0)
00120 {
00121 unsigned short data2 = bfd_getl16 (opbuf);
00122 if (tm->opcode2 == (data2 & tm->mask2))
00123 {
00124 if (size) *size = get_insn_size (memdata, tm);
00125 return tm;
00126 }
00127 }
00128 }
00129 else
00130 {
00131 if (size) *size = get_insn_size (memdata, tm);
00132 return tm;
00133 }
00134 }
00135 }
00136 for (tm = (template *) tic54x_paroptab; tm->name; tm++)
00137 {
00138 if (tm->opcode == (memdata & tm->mask))
00139 {
00140 if (size) *size = get_insn_size (memdata, tm);
00141 return tm;
00142 }
00143 }
00144
00145 if (size) *size = 1;
00146 return &tic54x_unknown_opcode;
00147 }
00148
00149 static int
00150 get_insn_size (unsigned short memdata, const template *insn)
00151 {
00152 int size;
00153
00154 if (insn->flags & FL_PAR)
00155 {
00156
00157 size = insn->words;
00158 }
00159 else
00160 {
00161 size = insn->words + has_lkaddr (memdata, insn);
00162 }
00163
00164 return size;
00165 }
00166
00167 int
00168 print_instruction (info, memaddr, opcode, tm_name, tm_operands, size, ext)
00169 disassemble_info *info;
00170 bfd_vma memaddr;
00171 unsigned short opcode;
00172 const char *tm_name;
00173 const enum optype tm_operands[];
00174 int size;
00175 int ext;
00176 {
00177 static int n;
00178
00179 char operand[4][64] = { {0},{0},{0},{0}, };
00180 bfd_byte buf[2];
00181 unsigned long opcode2 = 0;
00182 unsigned long lkaddr = 0;
00183 enum optype src = OP_None;
00184 enum optype dst = OP_None;
00185 int i, shift;
00186 char *comma = "";
00187
00188 info->fprintf_func (info->stream, "%-7s", tm_name);
00189
00190 if (size > 1)
00191 {
00192 int status = (*info->read_memory_func) (memaddr + 1, buf, 2, info);
00193 if (status != 0)
00194 return 0;
00195 lkaddr = opcode2 = bfd_getl16 (buf);
00196 if (size > 2)
00197 {
00198 status = (*info->read_memory_func) (memaddr + 2, buf, 2, info);
00199 if (status != 0)
00200 return 0;
00201 opcode2 = bfd_getl16 (buf);
00202 }
00203 }
00204
00205 for (i = 0; i < MAX_OPERANDS && OPTYPE (tm_operands[i]) != OP_None; i++)
00206 {
00207 char *next_comma = ",";
00208 int optional = (tm_operands[i] & OPT) != 0;
00209
00210 switch (OPTYPE (tm_operands[i]))
00211 {
00212 case OP_Xmem:
00213 sprint_dual_address (info, operand[i], XMEM (opcode));
00214 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00215 break;
00216 case OP_Ymem:
00217 sprint_dual_address (info, operand[i], YMEM (opcode));
00218 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00219 break;
00220 case OP_Smem:
00221 case OP_Sind:
00222 case OP_Lmem:
00223 info->fprintf_func (info->stream, "%s", comma);
00224 if (INDIRECT (opcode))
00225 {
00226 if (MOD (opcode) >= 12)
00227 {
00228 bfd_vma addr = lkaddr;
00229 int arf = ARF (opcode);
00230 int mod = MOD (opcode);
00231 if (mod == 15)
00232 info->fprintf_func (info->stream, "*(");
00233 else
00234 info->fprintf_func (info->stream, "*%sar%d(",
00235 (mod == 13 || mod == 14 ? "+" : ""),
00236 arf);
00237 (*(info->print_address_func)) ((bfd_vma) addr, info);
00238 info->fprintf_func (info->stream, ")%s",
00239 mod == 14 ? "%" : "");
00240 }
00241 else
00242 {
00243 sprint_indirect_address (info, operand[i], opcode);
00244 info->fprintf_func (info->stream, "%s", operand[i]);
00245 }
00246 }
00247 else
00248 {
00249
00250
00251 sprint_direct_address (info, operand[i], opcode);
00252 info->fprintf_func (info->stream, "%s", operand[i]);
00253 }
00254 break;
00255 case OP_dmad:
00256 info->fprintf_func (info->stream, "%s", comma);
00257 (*(info->print_address_func)) ((bfd_vma) opcode2, info);
00258 break;
00259 case OP_xpmad:
00260
00261 opcode2 += ((unsigned long) opcode & 0x7F) << 16;
00262
00263 case OP_pmad:
00264 info->fprintf_func (info->stream, "%s", comma);
00265 (*(info->print_address_func)) ((bfd_vma) opcode2, info);
00266 break;
00267 case OP_MMRX:
00268 sprint_mmr (info, operand[i], MMRX (opcode));
00269 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00270 break;
00271 case OP_MMRY:
00272 sprint_mmr (info, operand[i], MMRY (opcode));
00273 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00274 break;
00275 case OP_MMR:
00276 sprint_mmr (info, operand[i], MMR (opcode));
00277 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00278 break;
00279 case OP_PA:
00280 sprintf (operand[i], "pa%d", (unsigned) opcode2);
00281 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00282 break;
00283 case OP_SRC:
00284 src = SRC (ext ? opcode2 : opcode) ? OP_B : OP_A;
00285 sprintf (operand[i], (src == OP_B) ? "b" : "a");
00286 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00287 break;
00288 case OP_SRC1:
00289 src = SRC1 (ext ? opcode2 : opcode) ? OP_B : OP_A;
00290 sprintf (operand[i], (src == OP_B) ? "b" : "a");
00291 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00292 break;
00293 case OP_RND:
00294 dst = DST (opcode) ? OP_B : OP_A;
00295 sprintf (operand[i], (dst == OP_B) ? "a" : "b");
00296 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00297 break;
00298 case OP_DST:
00299 dst = DST (ext ? opcode2 : opcode) ? OP_B : OP_A;
00300 if (!optional || dst != src)
00301 {
00302 sprintf (operand[i], (dst == OP_B) ? "b" : "a");
00303 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00304 }
00305 else
00306 next_comma = comma;
00307 break;
00308 case OP_B:
00309 sprintf (operand[i], "b");
00310 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00311 break;
00312 case OP_A:
00313 sprintf (operand[i], "a");
00314 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00315 break;
00316 case OP_ARX:
00317 sprintf (operand[i], "ar%d", (int) ARX (opcode));
00318 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00319 break;
00320 case OP_SHIFT:
00321 shift = SHIFT (ext ? opcode2 : opcode);
00322 if (!optional || shift != 0)
00323 {
00324 sprintf (operand[i], "%d", shift);
00325 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00326 }
00327 else
00328 next_comma = comma;
00329 break;
00330 case OP_SHFT:
00331 shift = SHFT (opcode);
00332 if (!optional || shift != 0)
00333 {
00334 sprintf (operand[i], "%d", (unsigned) shift);
00335 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00336 }
00337 else
00338 next_comma = comma;
00339 break;
00340 case OP_lk:
00341 sprintf (operand[i], "#%d", (int) (short) opcode2);
00342 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00343 break;
00344 case OP_T:
00345 sprintf (operand[i], "t");
00346 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00347 break;
00348 case OP_TS:
00349 sprintf (operand[i], "ts");
00350 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00351 break;
00352 case OP_k8:
00353 sprintf (operand[i], "%d", (int) ((signed char) (opcode & 0xFF)));
00354 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00355 break;
00356 case OP_16:
00357 sprintf (operand[i], "16");
00358 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00359 break;
00360 case OP_ASM:
00361 sprintf (operand[i], "asm");
00362 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00363 break;
00364 case OP_BITC:
00365 sprintf (operand[i], "%d", (int) (opcode & 0xF));
00366 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00367 break;
00368 case OP_CC:
00369
00370 sprint_condition (info, operand[i], opcode);
00371 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00372 i = MAX_OPERANDS;
00373 break;
00374 case OP_CC2:
00375 sprint_cc2 (info, operand[i], opcode);
00376 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00377 break;
00378 case OP_CC3:
00379 {
00380 const char *code[] = { "eq", "lt", "gt", "neq" };
00381 sprintf (operand[i], code[CC3 (opcode)]);
00382 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00383 break;
00384 }
00385 case OP_123:
00386 {
00387 int code = (opcode >> 8) & 0x3;
00388 sprintf (operand[i], "%d", (code == 0) ? 1 : (code == 2) ? 2 : 3);
00389 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00390 break;
00391 }
00392 case OP_k5:
00393 sprintf (operand[i], "#%d",
00394 (int) (((signed char) opcode & 0x1F) << 3) >> 3);
00395 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00396 break;
00397 case OP_k8u:
00398 sprintf (operand[i], "#%d", (unsigned) (opcode & 0xFF));
00399 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00400 break;
00401 case OP_k3:
00402 sprintf (operand[i], "#%d", (int) (opcode & 0x7));
00403 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00404 break;
00405 case OP_lku:
00406 sprintf (operand[i], "#%d", (unsigned) opcode2);
00407 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00408 break;
00409 case OP_N:
00410 n = (opcode >> 9) & 0x1;
00411 sprintf (operand[i], "st%d", n);
00412 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00413 break;
00414 case OP_SBIT:
00415 {
00416 const char *status0[] = {
00417 "0", "1", "2", "3", "4", "5", "6", "7", "8",
00418 "ovb", "ova", "c", "tc", "13", "14", "15"
00419 };
00420 const char *status1[] = {
00421 "0", "1", "2", "3", "4",
00422 "cmpt", "frct", "c16", "sxm", "ovm", "10",
00423 "intm", "hm", "xf", "cpl", "braf"
00424 };
00425 sprintf (operand[i], "%s",
00426 n ? status1[SBIT (opcode)] : status0[SBIT (opcode)]);
00427 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00428 break;
00429 }
00430 case OP_12:
00431 sprintf (operand[i], "%d", (int) ((opcode >> 9) & 1) + 1);
00432 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00433 break;
00434 case OP_TRN:
00435 sprintf (operand[i], "trn");
00436 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00437 break;
00438 case OP_DP:
00439 sprintf (operand[i], "dp");
00440 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00441 break;
00442 case OP_k9:
00443
00444 sprintf (operand[i], "#%d", (int) (opcode & 0x1FF));
00445 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00446 break;
00447 case OP_ARP:
00448 sprintf (operand[i], "arp");
00449 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00450 break;
00451 case OP_031:
00452 sprintf (operand[i], "%d", (int) (opcode & 0x1F));
00453 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00454 break;
00455 default:
00456 sprintf (operand[i], "??? (0x%x)", tm_operands[i]);
00457 info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
00458 break;
00459 }
00460 comma = next_comma;
00461 }
00462 return 1;
00463 }
00464
00465 static int
00466 print_parallel_instruction (info, memaddr, opcode, ptm, size)
00467 disassemble_info *info;
00468 bfd_vma memaddr;
00469 unsigned short opcode;
00470 const template *ptm;
00471 int size;
00472 {
00473 print_instruction (info, memaddr, opcode,
00474 ptm->name, ptm->operand_types, size, 0);
00475 info->fprintf_func (info->stream, " || ");
00476 return print_instruction (info, memaddr, opcode,
00477 ptm->parname, ptm->paroperand_types, size, 0);
00478 }
00479
00480 static int
00481 sprint_dual_address (info, buf, code)
00482 disassemble_info *info ATTRIBUTE_UNUSED;
00483 char buf[];
00484 unsigned short code;
00485 {
00486 const char *formats[] = {
00487 "*ar%d",
00488 "*ar%d-",
00489 "*ar%d+",
00490 "*ar%d+0%%",
00491 };
00492 return sprintf (buf, formats[XMOD (code)], XARX (code));
00493 }
00494
00495 static int
00496 sprint_indirect_address (info, buf, opcode)
00497 disassemble_info *info ATTRIBUTE_UNUSED;
00498 char buf[];
00499 unsigned short opcode;
00500 {
00501 const char *formats[] = {
00502 "*ar%d",
00503 "*ar%d-",
00504 "*ar%d+",
00505 "*+ar%d",
00506 "*ar%d-0B",
00507 "*ar%d-0",
00508 "*ar%d+0",
00509 "*ar%d+0B",
00510 "*ar%d-%%",
00511 "*ar%d-0%%",
00512 "*ar%d+%%",
00513 "*ar%d+0%%",
00514 };
00515 return sprintf (buf, formats[MOD (opcode)], ARF (opcode));
00516 }
00517
00518 static int
00519 sprint_direct_address (info, buf, opcode)
00520 disassemble_info *info ATTRIBUTE_UNUSED;
00521 char buf[];
00522 unsigned short opcode;
00523 {
00524
00525 return sprintf (buf, "DP+0x%02x", (int) (opcode & 0x7F));
00526 }
00527
00528 static int
00529 sprint_mmr (info, buf, mmr)
00530 disassemble_info *info ATTRIBUTE_UNUSED;
00531 char buf[];
00532 int mmr;
00533 {
00534 symbol *reg = (symbol *) mmregs;
00535 while (reg->name != NULL)
00536 {
00537 if (mmr == reg->value)
00538 {
00539 sprintf (buf, "%s", (reg + 1)->name);
00540 return 1;
00541 }
00542 ++reg;
00543 }
00544 sprintf (buf, "MMR(%d)", mmr);
00545 return 0;
00546 }
00547
00548 static int
00549 sprint_cc2 (info, buf, opcode)
00550 disassemble_info *info ATTRIBUTE_UNUSED;
00551 char *buf;
00552 unsigned short opcode;
00553 {
00554 const char *cc2[] = {
00555 "??", "??", "ageq", "alt", "aneq", "aeq", "agt", "aleq",
00556 "??", "??", "bgeq", "blt", "bneq", "beq", "bgt", "bleq",
00557 };
00558 return sprintf (buf, "%s", cc2[opcode & 0xF]);
00559 }
00560
00561 static int
00562 sprint_condition (info, buf, opcode)
00563 disassemble_info *info ATTRIBUTE_UNUSED;
00564 char *buf;
00565 unsigned short opcode;
00566 {
00567 char *start = buf;
00568 const char *cmp[] = {
00569 "??", "??", "geq", "lt", "neq", "eq", "gt", "leq"
00570 };
00571 if (opcode & 0x40)
00572 {
00573 char acc = (opcode & 0x8) ? 'b' : 'a';
00574 if (opcode & 0x7)
00575 buf += sprintf (buf, "%c%s%s", acc, cmp[(opcode & 0x7)],
00576 (opcode & 0x20) ? ", " : "");
00577 if (opcode & 0x20)
00578 buf += sprintf (buf, "%c%s", acc, (opcode & 0x10) ? "ov" : "nov");
00579 }
00580 else if (opcode & 0x3F)
00581 {
00582 if (opcode & 0x30)
00583 buf += sprintf (buf, "%s%s",
00584 ((opcode & 0x30) == 0x30) ? "tc" : "ntc",
00585 (opcode & 0x0F) ? ", " : "");
00586 if (opcode & 0x0C)
00587 buf += sprintf (buf, "%s%s",
00588 ((opcode & 0x0C) == 0x0C) ? "c" : "nc",
00589 (opcode & 0x03) ? ", " : "");
00590 if (opcode & 0x03)
00591 buf += sprintf (buf, "%s",
00592 ((opcode & 0x03) == 0x03) ? "bio" : "nbio");
00593 }
00594 else
00595 buf += sprintf (buf, "unc");
00596
00597 return buf - start;
00598 }