1 /* Disassemble Imagination Technologies Meta instructions. 2 Copyright (C) 2013-2014 Free Software Foundation, Inc. 3 Contributed by Imagination Technologies Ltd. 4 5 This library is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 It is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 13 License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 18 MA 02110-1301, USA. */ 19 20 #include "sysdep.h" 21 #include "dis-asm.h" 22 #include "opintl.h" 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 #include "opcode/metag.h" 29 30 /* Column widths for printing. */ 31 #define PREFIX_WIDTH "10" 32 #define INSN_NAME_WIDTH "10" 33 34 #define OPERAND_WIDTH 92 35 #define ADDR_WIDTH 20 36 #define REG_WIDTH 64 37 #define DSP_PREFIX_WIDTH 17 38 39 /* Value to print if we fail to parse a register name. */ 40 const char unknown_reg[] = "?"; 41 42 /* Return the size of a GET or SET instruction. */ 43 unsigned int 44 metag_get_set_size_bytes (unsigned int opcode) 45 { 46 switch (((opcode) >> 24) & 0x5) 47 { 48 case 0x5: 49 return 8; 50 case 0x4: 51 return 4; 52 case 0x1: 53 return 2; 54 case 0x0: 55 return 1; 56 } 57 return 1; 58 } 59 60 /* Return the size of an extended GET or SET instruction. */ 61 unsigned int 62 metag_get_set_ext_size_bytes (unsigned int opcode) 63 { 64 switch (((opcode) >> 1) & 0x3) 65 { 66 case 0x3: 67 return 8; 68 case 0x2: 69 return 4; 70 case 0x1: 71 return 2; 72 case 0x0: 73 return 1; 74 } 75 return 1; 76 } 77 78 /* Return the size of a conditional SET instruction. */ 79 unsigned int 80 metag_cond_set_size_bytes (unsigned int opcode) 81 { 82 switch (opcode & 0x201) 83 { 84 case 0x201: 85 return 8; 86 case 0x200: 87 return 4; 88 case 0x001: 89 return 2; 90 case 0x000: 91 return 1; 92 } 93 return 1; 94 } 95 96 /* Return a value sign-extended. */ 97 static int 98 sign_extend (int n, unsigned int bits) 99 { 100 int mask = 1 << (bits - 1); 101 return -(n & mask) | n; 102 } 103 104 /* Return the short interpretation of UNIT. */ 105 static unsigned int 106 short_unit (unsigned int unit) 107 { 108 if (unit == UNIT_CT) 109 return UNIT_A1; 110 else 111 return unit; 112 } 113 114 /* Return the register corresponding to UNIT and NUMBER or NULL. */ 115 static const metag_reg * 116 lookup_reg (unsigned int unit, unsigned int number) 117 { 118 size_t i; 119 120 for (i = 0; i < sizeof(metag_regtab)/sizeof(metag_regtab[0]); i++) 121 { 122 const metag_reg *reg = &metag_regtab[i]; 123 124 if (reg->unit == unit && reg->no == number) 125 return reg; 126 } 127 return NULL; 128 } 129 130 131 /* Return the register name corresponding to UNIT and NUMBER or NULL. */ 132 static const char * 133 lookup_reg_name (unsigned int unit, unsigned int number) 134 { 135 const metag_reg *reg; 136 137 reg = lookup_reg (unit, number); 138 139 if (reg) 140 return reg->name; 141 else 142 return unknown_reg; 143 } 144 145 /* Return the unit that is the pair of UNIT. */ 146 static unsigned int 147 get_pair_unit (unsigned int unit) 148 { 149 switch (unit) 150 { 151 case UNIT_D0: 152 return UNIT_D1; 153 case UNIT_D1: 154 return UNIT_D0; 155 case UNIT_A0: 156 return UNIT_A1; 157 case UNIT_A1: 158 return UNIT_A0; 159 default: 160 return unit; 161 } 162 } 163 164 /* Return the name of the pair register for UNIT and NUMBER or NULL. */ 165 static const char * 166 lookup_pair_reg_name (unsigned int unit, unsigned int number) 167 { 168 if (unit == UNIT_FX) 169 return lookup_reg_name (unit, number + 1); 170 else 171 return lookup_reg_name (get_pair_unit (unit), number); 172 } 173 174 /* Return the name of the accumulator register for PART. */ 175 static const char * 176 lookup_acf_name (unsigned int part) 177 { 178 size_t i; 179 180 for (i = 0; i < sizeof(metag_acftab)/sizeof(metag_acftab[0]); i++) 181 { 182 const metag_acf *acf = &metag_acftab[i]; 183 184 if (acf->part == part) 185 return acf->name; 186 } 187 return "ACF.?"; 188 } 189 190 /* Return the register name for the O2R register for UNIT and NUMBER. */ 191 static const char * 192 lookup_o2r (enum metag_unit unit, unsigned int number) 193 { 194 unsigned int o2r_unit; 195 enum metag_unit actual_unit = UNIT_A0; 196 const metag_reg *reg; 197 198 o2r_unit = (number & ~O2R_REG_MASK) >> 3; 199 number = number & O2R_REG_MASK; 200 201 if (unit == UNIT_A0) 202 { 203 switch (o2r_unit) 204 { 205 case 0: 206 actual_unit = UNIT_A1; 207 break; 208 case 1: 209 actual_unit = UNIT_D0; 210 break; 211 case 2: 212 actual_unit = UNIT_RD; 213 break; 214 case 3: 215 actual_unit = UNIT_D1; 216 break; 217 } 218 } 219 else if (unit == UNIT_A1) 220 { 221 switch (o2r_unit) 222 { 223 case 0: 224 actual_unit = UNIT_D1; 225 break; 226 case 1: 227 actual_unit = UNIT_D0; 228 break; 229 case 2: 230 actual_unit = UNIT_RD; 231 break; 232 case 3: 233 actual_unit = UNIT_A0; 234 break; 235 } 236 } 237 else if (unit == UNIT_D0) 238 { 239 switch (o2r_unit) 240 { 241 case 0: 242 actual_unit = UNIT_A1; 243 break; 244 case 1: 245 actual_unit = UNIT_D1; 246 break; 247 case 2: 248 actual_unit = UNIT_RD; 249 break; 250 case 3: 251 actual_unit = UNIT_A0; 252 break; 253 } 254 } 255 else if (unit == UNIT_D1) 256 { 257 switch (o2r_unit) 258 { 259 case 0: 260 actual_unit = UNIT_A1; 261 break; 262 case 1: 263 actual_unit = UNIT_D0; 264 break; 265 case 2: 266 actual_unit = UNIT_RD; 267 break; 268 case 3: 269 actual_unit = UNIT_A0; 270 break; 271 } 272 } 273 274 reg = lookup_reg (actual_unit, number); 275 276 if (reg) 277 return reg->name; 278 else 279 return unknown_reg; 280 } 281 282 /* Return the string for split condition code CODE. */ 283 static const char * 284 lookup_scc_flags (unsigned int code) 285 { 286 size_t i; 287 288 for (i = 0; i < sizeof (metag_dsp_scondtab) / sizeof (metag_dsp_scondtab[0]); i++) 289 { 290 if (metag_dsp_scondtab[i].code == code) 291 { 292 return metag_dsp_scondtab[i].name; 293 } 294 } 295 return NULL; 296 } 297 298 /* Return the string for FPU split condition code CODE. */ 299 static const char * 300 lookup_fpu_scc_flags (unsigned int code) 301 { 302 size_t i; 303 304 for (i = 0; i < sizeof (metag_fpu_scondtab) / sizeof (metag_fpu_scondtab[0]); i++) 305 { 306 if (metag_fpu_scondtab[i].code == code) 307 { 308 return metag_fpu_scondtab[i].name; 309 } 310 } 311 return NULL; 312 } 313 314 /* Print an instruction with PREFIX, NAME and OPERANDS. */ 315 static void 316 print_insn (disassemble_info *outf, const char *prefix, const char *name, 317 const char *operands) 318 { 319 outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%-" INSN_NAME_WIDTH "s%s", prefix, name, operands); 320 } 321 322 /* Print an instruction with no operands. */ 323 static void 324 print_none (unsigned int insn_word ATTRIBUTE_UNUSED, 325 bfd_vma pc ATTRIBUTE_UNUSED, 326 const insn_template *template, 327 disassemble_info *outf) 328 { 329 outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%s", "", 330 template->name); 331 } 332 333 /* Print a unit to unit MOV instruction. */ 334 static void 335 print_mov_u2u (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 336 const insn_template *template, 337 disassemble_info *outf) 338 { 339 unsigned int dest_unit, dest_no, src_unit, src_no; 340 unsigned int is_kick = (insn_word & 0x1) && !((insn_word >> 9) & 0x1); 341 unsigned int major = MAJOR_OPCODE (insn_word); 342 unsigned int minor = MINOR_OPCODE (insn_word); 343 char buf[OPERAND_WIDTH]; 344 const char *dest_reg; 345 const char *src_reg; 346 347 dest_unit = (insn_word >> 5) & UNIT_MASK; 348 dest_no = (insn_word >> 14) & REG_MASK; 349 350 dest_reg = lookup_reg_name (dest_unit, dest_no); 351 352 if (is_kick) 353 src_unit = UNIT_TR; 354 else 355 src_unit = (insn_word >> 10) & UNIT_MASK; 356 357 /* This is really an RTI/RTH. No, really. */ 358 if (major == OPC_MISC && 359 minor == 0x3 && 360 src_unit == 0xf) 361 { 362 if (insn_word & 0x800000) 363 outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%s", "", 364 "RTI"); 365 else 366 outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%s", "", 367 "RTH"); 368 369 return; 370 } 371 372 src_no = (insn_word >> 19) & REG_MASK; 373 374 src_reg = lookup_reg_name (src_unit, src_no); 375 376 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 377 378 if (dest_unit == UNIT_FX || src_unit == UNIT_FX) 379 print_insn (outf, "F", template->name, buf); 380 else 381 print_insn (outf, "", template->name, buf); 382 } 383 384 /* Print a MOV to port instruction. */ 385 static void 386 print_mov_port (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 387 const insn_template *template, 388 disassemble_info *outf) 389 { 390 unsigned int dest_unit, dest1_no, dest2_no, src_unit, src_no; 391 unsigned int is_movl = MINOR_OPCODE (insn_word) == MOVL_MINOR; 392 char buf[OPERAND_WIDTH]; 393 const char *dest_reg; 394 const char *pair_reg; 395 const char *src_reg; 396 397 if (is_movl) 398 dest_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK); 399 else 400 dest_unit = (insn_word >> 5) & UNIT_MASK; 401 402 dest1_no = (insn_word >> 14) & REG_MASK; 403 dest2_no = (insn_word >> 9) & REG_MASK; 404 405 dest_reg = lookup_reg_name (dest_unit, dest1_no); 406 pair_reg = lookup_pair_reg_name (dest_unit, dest2_no); 407 408 src_unit = UNIT_RD; 409 src_no = 0; 410 411 src_reg = lookup_reg_name (src_unit, src_no); 412 413 if (is_movl) 414 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, pair_reg, src_reg); 415 else 416 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 417 418 if (dest_unit == UNIT_FX) 419 print_insn (outf, "F", template->name, buf); 420 else 421 print_insn (outf, "", template->name, buf); 422 } 423 424 /* Return the number of bits set in rmask. */ 425 static unsigned int hweight (unsigned int rmask) 426 { 427 unsigned int count; 428 429 for (count = 0; rmask; count++) 430 { 431 rmask &= rmask - 1; 432 } 433 434 return count; 435 } 436 437 /* Print a MOVL to TTREC instruction. */ 438 static void 439 print_movl_ttrec (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 440 const insn_template *template, 441 disassemble_info *outf) 442 { 443 unsigned int dest_unit, dest_no, src1_no, src2_no, src_unit; 444 char buf[OPERAND_WIDTH]; 445 const char *dest_reg; 446 const char *src_reg; 447 const char *pair_reg; 448 449 dest_unit = UNIT_TT; 450 dest_no = 3; 451 452 dest_reg = lookup_reg_name (dest_unit, dest_no); 453 454 src1_no = (insn_word >> 19) & REG_MASK; 455 src2_no = (insn_word >> 14) & REG_MASK; 456 457 src_unit = short_unit ((insn_word >> 7) & SHORT_UNIT_MASK); 458 459 src_reg = lookup_reg_name (src_unit, src1_no); 460 pair_reg = lookup_pair_reg_name (src_unit, src2_no); 461 462 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src_reg, pair_reg); 463 464 print_insn (outf, "", template->name, buf); 465 } 466 467 /* Format a GET or SET address mode string from INSN_WORD into BUF. */ 468 static void 469 get_set_addr_str (char *buf, unsigned int buf_size, unsigned int size, 470 unsigned int insn_word) 471 { 472 const char *base_reg; 473 unsigned int base_unit, base_no; 474 unsigned int imm = (insn_word >> 25) & 1; 475 unsigned int ua = (insn_word >> 7) & 1; 476 unsigned int pp = insn_word & 1; 477 478 base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK); 479 base_no = (insn_word >> 14) & REG_MASK; 480 481 base_reg = lookup_reg_name (base_unit, base_no); 482 483 if (imm) 484 { 485 int offset = (insn_word >> 8) & GET_SET_IMM_MASK; 486 487 offset = sign_extend (offset, GET_SET_IMM_BITS); 488 489 if (offset == 0) 490 { 491 snprintf (buf, buf_size, "[%s]", base_reg); 492 return; 493 } 494 495 if (offset == 1 && ua) 496 { 497 if (pp) 498 snprintf (buf, buf_size, "[%s++]", base_reg); 499 else 500 snprintf (buf, buf_size, "[++%s]", base_reg); 501 502 return; 503 } 504 else if (offset == -1 && ua) 505 { 506 if (pp) 507 snprintf (buf, buf_size, "[%s--]", base_reg); 508 else 509 snprintf (buf, buf_size, "[--%s]", base_reg); 510 511 return; 512 } 513 514 offset = offset * size; 515 516 if (ua) 517 { 518 if (pp) 519 snprintf (buf, buf_size, "[%s+#%d++]", base_reg, offset); 520 else 521 snprintf (buf, buf_size, "[%s++#%d]", base_reg, offset); 522 } 523 else 524 snprintf (buf, buf_size, "[%s+#%d]", base_reg, offset); 525 } 526 else 527 { 528 const char *offset_reg; 529 unsigned int offset_no; 530 531 offset_no = (insn_word >> 9) & REG_MASK; 532 533 offset_reg = lookup_reg_name (base_unit, offset_no); 534 535 if (ua) 536 { 537 if (pp) 538 snprintf (buf, buf_size, "[%s+%s++]", base_reg, offset_reg); 539 else 540 snprintf (buf, buf_size, "[%s++%s]", base_reg, offset_reg); 541 } 542 else 543 snprintf (buf, buf_size, "[%s+%s]", base_reg, offset_reg); 544 } 545 } 546 547 /* Format an extended GET or SET address mode string from INSN_WORD into BUF. */ 548 static void 549 get_set_ext_addr_str (char *buf, unsigned int buf_size, unsigned int size, 550 unsigned int insn_word) 551 { 552 const char *base_reg; 553 unsigned int base_unit, base_no; 554 int offset; 555 556 base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK); 557 base_no = insn_word & EXT_BASE_REG_MASK; 558 559 base_reg = lookup_reg_name (base_unit, base_no); 560 561 offset = (insn_word >> 7) & GET_SET_EXT_IMM_MASK; 562 563 offset = sign_extend (offset, GET_SET_EXT_IMM_BITS); 564 565 offset = offset * size; 566 567 if (offset == 0) 568 { 569 snprintf (buf, buf_size, "[%s]", base_reg); 570 } 571 else 572 { 573 snprintf (buf, buf_size, "[%s+#%d]", base_reg, offset); 574 } 575 } 576 577 /* Format an MGET or MSET address mode string from INSN_WORD into BUF. */ 578 static void 579 mget_mset_addr_str (char *buf, unsigned int buf_size, 580 unsigned int insn_word) 581 { 582 const char *base_reg; 583 unsigned int base_unit, base_no; 584 585 base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK); 586 base_no = (insn_word >> 14) & REG_MASK; 587 588 base_reg = lookup_reg_name (base_unit, base_no); 589 590 snprintf (buf, buf_size, "[%s++]", base_reg); 591 } 592 593 /* Format a conditional SET address mode string from INSN_WORD into BUF. */ 594 static void 595 cond_set_addr_str (char *buf, unsigned int buf_size, 596 unsigned int insn_word) 597 { 598 const char *base_reg; 599 unsigned int base_unit, base_no; 600 601 base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK); 602 base_no = (insn_word >> 14) & REG_MASK; 603 604 base_reg = lookup_reg_name (base_unit, base_no); 605 606 snprintf (buf, buf_size, "[%s]", base_reg); 607 } 608 609 /* Format a cache instruction address mode string from INSN_WORD into BUF. */ 610 static void 611 cache_addr_str (char *buf, unsigned int buf_size, unsigned int insn_word, 612 int width) 613 { 614 const char *base_reg; 615 unsigned int base_unit, base_no; 616 int offset; 617 618 base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK); 619 base_no = (insn_word >> 14) & REG_MASK; 620 621 base_reg = lookup_reg_name (base_unit, base_no); 622 623 offset = (insn_word >> 8) & GET_SET_IMM_MASK; 624 625 offset = sign_extend (offset, GET_SET_IMM_BITS); 626 627 offset = offset * width; 628 629 if (offset == 0) 630 { 631 snprintf (buf, buf_size, "[%s]", base_reg); 632 } 633 else 634 { 635 snprintf (buf, buf_size, "[%s+#%d]", base_reg, offset); 636 } 637 } 638 639 /* Format a list of registers starting at REG_UNIT and REG_NO and conforming 640 to RMASK into BUF. */ 641 static void 642 lookup_reg_list (char *reg_buf, size_t buf_len, unsigned int reg_unit, 643 unsigned int reg_no, unsigned int rmask, 644 bfd_boolean is_fpu_64bit) 645 { 646 const char *regs[MGET_MSET_MAX_REGS]; 647 size_t used_regs = 1, i, remaining; 648 649 regs[0] = lookup_reg_name (reg_unit, reg_no); 650 651 for (i = 1; i < MGET_MSET_MAX_REGS; i++) 652 { 653 if (rmask & 1) 654 { 655 if (is_fpu_64bit) 656 regs[used_regs] = lookup_reg_name (reg_unit, reg_no + (i * 2)); 657 else 658 regs[used_regs] = lookup_reg_name (reg_unit, reg_no + i); 659 used_regs++; 660 } 661 rmask = rmask >> 1; 662 } 663 664 remaining = buf_len; 665 666 for (i = 0; i < used_regs; i++) 667 { 668 size_t len; 669 if (i == 0) 670 len = snprintf(reg_buf, remaining, "%s", regs[i]); 671 else 672 len = snprintf(reg_buf, remaining, ",%s", regs[i]); 673 674 reg_buf += len; 675 remaining -= len; 676 } 677 } 678 679 /* Print a GET instruction. */ 680 static void 681 print_get (char *buf, char *addr_buf, unsigned int size, 682 const char *dest_reg, const char *pair_reg, unsigned int reg_unit, 683 const insn_template *template, 684 disassemble_info *outf) 685 { 686 if (size == 8) 687 { 688 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, pair_reg, 689 addr_buf); 690 } 691 else 692 { 693 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, addr_buf); 694 } 695 696 if (reg_unit == UNIT_FX) 697 print_insn (outf, "F", template->name, buf); 698 else 699 print_insn (outf, "", template->name, buf); 700 } 701 702 /* Print a SET instruction. */ 703 static void 704 print_set (char *buf, char *addr_buf, unsigned int size, 705 const char *src_reg, const char *pair_reg, unsigned int reg_unit, 706 const insn_template *template, 707 disassemble_info *outf) 708 { 709 if (size == 8) 710 { 711 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf, src_reg, pair_reg); 712 } 713 else 714 { 715 snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, src_reg); 716 } 717 718 if (reg_unit == UNIT_FX) 719 print_insn (outf, "F", template->name, buf); 720 else 721 print_insn (outf, "", template->name, buf); 722 } 723 724 /* Print a GET or SET instruction. */ 725 static void 726 print_get_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 727 const insn_template *template, 728 disassemble_info *outf) 729 { 730 bfd_boolean is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET; 731 char buf[OPERAND_WIDTH]; 732 char addr_buf[ADDR_WIDTH]; 733 unsigned int reg_unit, reg_no; 734 unsigned int size = metag_get_set_size_bytes (insn_word); 735 const char *reg_name; 736 const char *pair_reg; 737 738 reg_unit = (insn_word >> 1) & UNIT_MASK; 739 reg_no = (insn_word >> 19) & REG_MASK; 740 741 /* SETs should always print RD. */ 742 if (!is_get && reg_unit == UNIT_RD) 743 reg_no = 0; 744 745 reg_name = lookup_reg_name (reg_unit, reg_no); 746 747 pair_reg = lookup_pair_reg_name (reg_unit, reg_no); 748 749 get_set_addr_str (addr_buf, ADDR_WIDTH, size, insn_word); 750 751 if (is_get) 752 { 753 /* RD regs are 64 bits wide so don't use the pair syntax. */ 754 if (reg_unit == UNIT_RD) 755 print_get (buf, addr_buf, 4, reg_name, pair_reg, reg_unit, 756 template, outf); 757 else 758 print_get (buf, addr_buf, size, reg_name, pair_reg, reg_unit, 759 template, outf); 760 } 761 else 762 { 763 /* RD regs are 64 bits wide so don't use the pair syntax. */ 764 if (reg_unit == UNIT_RD) 765 print_set (buf, addr_buf, 4, reg_name, pair_reg, reg_unit, 766 template, outf); 767 else 768 print_set (buf, addr_buf, size, reg_name, pair_reg, reg_unit, 769 template, outf); 770 } 771 } 772 773 /* Print an extended GET or SET instruction. */ 774 static void 775 print_get_set_ext (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 776 const insn_template *template, 777 disassemble_info *outf) 778 { 779 bfd_boolean is_get = MINOR_OPCODE (template->meta_opcode) == GET_EXT_MINOR; 780 bfd_boolean is_mov = MINOR_OPCODE (template->meta_opcode) == MOV_EXT_MINOR; 781 char buf[OPERAND_WIDTH]; 782 char addr_buf[ADDR_WIDTH]; 783 unsigned int reg_unit, reg_no; 784 unsigned int size = metag_get_set_ext_size_bytes (insn_word); 785 const char *reg_name; 786 const char *pair_reg; 787 788 if (is_mov) 789 reg_unit = UNIT_RD; 790 else 791 reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK); 792 793 reg_no = (insn_word >> 19) & REG_MASK; 794 795 reg_name = lookup_reg_name (reg_unit, reg_no); 796 797 pair_reg = lookup_pair_reg_name (reg_unit, reg_no); 798 799 get_set_ext_addr_str (addr_buf, ADDR_WIDTH, size, insn_word); 800 801 if (is_get) 802 print_get (buf, addr_buf, size, reg_name, pair_reg, reg_unit, 803 template, outf); 804 else if (is_mov) 805 print_get (buf, addr_buf, 4, reg_name, pair_reg, reg_unit, 806 template, outf); 807 else 808 print_set (buf, addr_buf, size, reg_name, pair_reg, reg_unit, 809 template, outf); 810 } 811 812 /* Print an MGET or MSET instruction. */ 813 static void 814 print_mget_mset (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 815 const insn_template *template, 816 disassemble_info *outf) 817 { 818 bfd_boolean is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET; 819 bfd_boolean is_fpu = (MINOR_OPCODE (template->meta_opcode) & 0x6) == 0x6; 820 bfd_boolean is_64bit = (MINOR_OPCODE (template->meta_opcode) & 0x1) == 0x1; 821 char buf[OPERAND_WIDTH]; 822 char addr_buf[ADDR_WIDTH]; 823 char reg_buf[REG_WIDTH]; 824 unsigned int reg_unit, reg_no, rmask; 825 826 if (is_fpu) 827 reg_unit = UNIT_FX; 828 else 829 reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK); 830 831 reg_no = (insn_word >> 19) & REG_MASK; 832 rmask = (insn_word >> 7) & RMASK_MASK; 833 834 lookup_reg_list (reg_buf, REG_WIDTH, reg_unit, reg_no, rmask, 835 is_fpu && is_64bit); 836 837 mget_mset_addr_str (addr_buf, ADDR_WIDTH, insn_word); 838 839 if (is_get) 840 snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_buf, addr_buf); 841 else 842 snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_buf); 843 844 if (is_fpu) 845 print_insn (outf, "F", template->name, buf); 846 else 847 print_insn (outf, "", template->name, buf); 848 } 849 850 /* Print a conditional SET instruction. */ 851 static void 852 print_cond_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 853 const insn_template *template, 854 disassemble_info *outf) 855 { 856 char buf[OPERAND_WIDTH]; 857 char addr_buf[ADDR_WIDTH]; 858 unsigned int src_unit, src_no; 859 unsigned int size = metag_cond_set_size_bytes (insn_word); 860 const char *src_reg; 861 const char *pair_reg; 862 863 src_unit = (insn_word >> 10) & UNIT_MASK; 864 src_no = (insn_word >> 19) & REG_MASK; 865 866 if (src_unit == UNIT_RD) 867 src_no = 0; 868 869 src_reg = lookup_reg_name (src_unit, src_no); 870 871 pair_reg = lookup_pair_reg_name (src_unit, src_no); 872 873 cond_set_addr_str (addr_buf, ADDR_WIDTH, insn_word); 874 875 if (src_unit == UNIT_RD) 876 print_set (buf, addr_buf, 4, src_reg, pair_reg, src_unit, 877 template, outf); 878 else 879 print_set (buf, addr_buf, size, src_reg, pair_reg, src_unit, 880 template, outf); 881 } 882 883 /* Print a MMOV instruction. */ 884 static void 885 print_mmov (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 886 const insn_template *template, 887 disassemble_info *outf) 888 { 889 unsigned int is_fpu = template->insn_type == INSN_FPU; 890 unsigned int is_prime = ((MINOR_OPCODE (template->meta_opcode) & 0x2) && 891 !is_fpu); 892 unsigned int is_64bit = MINOR_OPCODE (template->meta_opcode) & 0x1; 893 unsigned int is_dsp = template->meta_opcode & 0x1; 894 unsigned int dest_unit, dest_no, rmask; 895 char buf[OPERAND_WIDTH]; 896 char reg_buf[REG_WIDTH]; 897 char addr_buf[ADDR_WIDTH]; 898 899 if (is_fpu) 900 dest_no = (insn_word >> 14) & REG_MASK; 901 else 902 dest_no = (insn_word >> 19) & REG_MASK; 903 904 rmask = (insn_word >> 7) & RMASK_MASK; 905 906 if (is_prime) 907 { 908 const char *dest_reg; 909 const char *base_reg; 910 unsigned int base_unit, base_no; 911 int i, count = hweight (rmask); 912 913 dest_reg = lookup_reg_name (UNIT_RD, dest_no); 914 915 strcpy (reg_buf, dest_reg); 916 917 for (i = 0; i < count; i++) 918 { 919 strcat (reg_buf, ","); 920 strcat (reg_buf, dest_reg); 921 } 922 923 base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK); 924 base_no = (insn_word >> 14) & REG_MASK; 925 926 base_reg = lookup_reg_name (base_unit, base_no); 927 928 snprintf (addr_buf, ADDR_WIDTH, "[%s++]", base_reg); 929 930 snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_buf, addr_buf); 931 } 932 else 933 { 934 if (is_fpu) 935 dest_unit = UNIT_FX; 936 else 937 dest_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK); 938 939 lookup_reg_list (reg_buf, REG_WIDTH, dest_unit, dest_no, rmask, 940 is_fpu && is_64bit); 941 942 snprintf (buf, OPERAND_WIDTH, "%s,RD", reg_buf); 943 } 944 945 if (is_dsp) 946 { 947 char prefix_buf[10] = {0}; 948 if (is_prime) 949 { 950 if (dest_no == 22 || dest_no == 23) 951 strcpy (prefix_buf, "DB"); 952 else if (dest_no == 24) 953 strcpy (prefix_buf, "DBH"); 954 else if (dest_no == 25) 955 strcpy (prefix_buf, "DWH"); 956 else if (dest_no == 31) 957 strcpy (prefix_buf, "DW"); 958 } 959 else 960 strcpy (prefix_buf, "DW"); 961 print_insn (outf, prefix_buf, template->name, buf); 962 } 963 else if (is_fpu) 964 print_insn (outf, "F", template->name, buf); 965 else 966 print_insn (outf, "", template->name, buf); 967 } 968 969 /* Print an MDRD instruction. */ 970 static void 971 print_mdrd (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 972 const insn_template *template, 973 disassemble_info *outf) 974 { 975 unsigned int rmask, count; 976 char buf[OPERAND_WIDTH]; 977 978 rmask = (insn_word >> 7) & RMASK_MASK; 979 980 count = hweight (rmask); 981 982 snprintf (buf, OPERAND_WIDTH, "#%#x", count + 1); 983 984 print_insn (outf, "", template->name, buf); 985 } 986 987 /* Print an XFR instruction. */ 988 static void 989 print_xfr (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 990 const insn_template *template, 991 disassemble_info *outf) 992 { 993 char buf[OPERAND_WIDTH]; 994 char dest_buf[ADDR_WIDTH]; 995 char src_buf[ADDR_WIDTH]; 996 unsigned int dest_unit, src_unit; 997 unsigned int dest_no, src_no; 998 unsigned int us, ud, pp; 999 const char *dest_base_reg; 1000 const char *dest_offset_reg; 1001 const char *src_base_reg; 1002 const char *src_offset_reg; 1003 1004 src_unit = short_unit ((insn_word >> 2) & SHORT_UNIT_MASK); 1005 src_no = (insn_word >> 19) & REG_MASK; 1006 1007 src_base_reg = lookup_reg_name (src_unit, src_no); 1008 1009 src_no = (insn_word >> 14) & REG_MASK; 1010 1011 src_offset_reg = lookup_reg_name (src_unit, src_no); 1012 1013 dest_unit = short_unit (insn_word & SHORT_UNIT_MASK); 1014 dest_no = (insn_word >> 9) & REG_MASK; 1015 1016 dest_base_reg = lookup_reg_name (dest_unit, dest_no); 1017 1018 dest_no = (insn_word >> 4) & REG_MASK; 1019 1020 dest_offset_reg = lookup_reg_name (dest_unit, dest_no); 1021 1022 us = (insn_word >> 27) & 0x1; 1023 ud = (insn_word >> 26) & 0x1; 1024 pp = (insn_word >> 24) & 0x1; 1025 1026 if (us) 1027 if (pp) 1028 snprintf (src_buf, ADDR_WIDTH, "[%s+%s++]", src_base_reg, 1029 src_offset_reg); 1030 else 1031 snprintf (src_buf, ADDR_WIDTH, "[%s++%s]", src_base_reg, 1032 src_offset_reg); 1033 else 1034 snprintf (src_buf, ADDR_WIDTH, "[%s+%s]", src_base_reg, 1035 src_offset_reg); 1036 1037 if (ud) 1038 if (pp) 1039 snprintf (dest_buf, ADDR_WIDTH, "[%s+%s++]", dest_base_reg, 1040 dest_offset_reg); 1041 else 1042 snprintf (dest_buf, ADDR_WIDTH, "[%s++%s]", dest_base_reg, 1043 dest_offset_reg); 1044 else 1045 snprintf (dest_buf, ADDR_WIDTH, "[%s+%s]", dest_base_reg, 1046 dest_offset_reg); 1047 1048 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_buf, src_buf); 1049 1050 print_insn (outf, "", template->name, buf); 1051 } 1052 1053 /* Print a MOV to control unit instruction. */ 1054 static void 1055 print_mov_ct (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1056 const insn_template *template, 1057 disassemble_info *outf) 1058 { 1059 char buf[OPERAND_WIDTH]; 1060 unsigned int reg_no; 1061 unsigned int se = (insn_word >> 1) & 0x1; 1062 unsigned int is_trace = (insn_word >> 2) & 0x1; 1063 int value; 1064 const char *dest_reg; 1065 1066 reg_no = (insn_word >> 19) & REG_MASK; 1067 1068 if (is_trace) 1069 dest_reg = lookup_reg_name (UNIT_TT, reg_no); 1070 else 1071 dest_reg = lookup_reg_name (UNIT_CT, reg_no); 1072 1073 value = (insn_word >> 3) & IMM16_MASK; 1074 1075 if (se) 1076 { 1077 value = sign_extend (value, IMM16_BITS); 1078 snprintf (buf, OPERAND_WIDTH, "%s,#%d", dest_reg, value); 1079 } 1080 else 1081 { 1082 snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value); 1083 } 1084 1085 print_insn (outf, "", template->name, buf); 1086 } 1087 1088 /* Print a SWAP instruction. */ 1089 static void 1090 print_swap (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1091 const insn_template *template, 1092 disassemble_info *outf) 1093 { 1094 char buf[OPERAND_WIDTH]; 1095 unsigned int dest_no, src_no; 1096 unsigned int dest_unit, src_unit; 1097 const char *dest_reg; 1098 const char *src_reg; 1099 1100 src_unit = (insn_word >> 10) & UNIT_MASK; 1101 src_no = (insn_word >> 19) & REG_MASK; 1102 1103 src_reg = lookup_reg_name (src_unit, src_no); 1104 1105 dest_unit = (insn_word >> 5) & UNIT_MASK; 1106 dest_no = (insn_word >> 14) & REG_MASK; 1107 1108 dest_reg = lookup_reg_name (dest_unit, dest_no); 1109 1110 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 1111 1112 if (dest_unit == UNIT_FX || src_unit == UNIT_FX) 1113 print_insn (outf, "F", template->name, buf); 1114 else 1115 print_insn (outf, "", template->name, buf); 1116 } 1117 1118 /* Print a SWAP instruction. */ 1119 static void 1120 print_jump (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1121 const insn_template *template, 1122 disassemble_info *outf) 1123 { 1124 char buf[OPERAND_WIDTH]; 1125 unsigned int reg_no, reg_unit; 1126 const char *reg_name; 1127 int value; 1128 1129 reg_unit = short_unit (insn_word & SHORT_UNIT_MASK); 1130 reg_no = (insn_word >> 19) & REG_MASK; 1131 1132 reg_name = lookup_reg_name (reg_unit, reg_no); 1133 1134 value = (insn_word >> 3) & IMM16_MASK; 1135 1136 snprintf (buf, OPERAND_WIDTH, "%s,#%#x", reg_name, value); 1137 1138 print_insn (outf, "", template->name, buf); 1139 } 1140 1141 /* Print a CALLR instruction. */ 1142 static void 1143 print_callr (unsigned int insn_word, bfd_vma pc, const insn_template *template, 1144 disassemble_info *outf) 1145 { 1146 char buf[OPERAND_WIDTH]; 1147 unsigned int reg_no, reg_unit; 1148 const char *reg_name; 1149 int value; 1150 1151 reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK); 1152 reg_no = insn_word & CALLR_REG_MASK; 1153 1154 reg_name = lookup_reg_name (reg_unit, reg_no); 1155 1156 value = (insn_word >> 5) & IMM19_MASK; 1157 1158 value = sign_extend (value, IMM19_BITS); 1159 1160 value = value * 4; 1161 1162 value += pc; 1163 1164 snprintf (buf, OPERAND_WIDTH, "%s,", reg_name); 1165 1166 print_insn (outf, "", template->name, buf); 1167 1168 outf->print_address_func (value, outf); 1169 } 1170 1171 /* Print a GP ALU instruction. */ 1172 static void 1173 print_alu (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1174 const insn_template *template, 1175 disassemble_info *outf) 1176 { 1177 char buf[OPERAND_WIDTH]; 1178 unsigned int is_addr_op = MAJOR_OPCODE (template->meta_opcode) == OPC_ADDR; 1179 unsigned int is_mul = MAJOR_OPCODE (template->meta_opcode) == OPC_MUL; 1180 unsigned int dest_no, src1_no, src2_no; 1181 unsigned int imm = (insn_word >> 25) & 0x1; 1182 unsigned int cond = (insn_word >> 26) & 0x1; 1183 unsigned int o1z = 0; 1184 unsigned int o2r = insn_word & 0x1; 1185 unsigned int unit_bit = (insn_word >> 24) & 0x1; 1186 unsigned int ca = (insn_word >> 5) & 0x1; 1187 unsigned int se = (insn_word >> 1) & 0x1; 1188 bfd_boolean is_quickrot = template->arg_type & GP_ARGS_QR; 1189 enum metag_unit base_unit; 1190 enum metag_unit dest_unit; 1191 const char *dest_reg; 1192 const char *src1_reg; 1193 const char *src2_reg; 1194 int value; 1195 1196 if ((MAJOR_OPCODE (template->meta_opcode) == OPC_ADDR || 1197 MAJOR_OPCODE (template->meta_opcode) == OPC_ADD || 1198 MAJOR_OPCODE (template->meta_opcode) == OPC_SUB) && 1199 ((insn_word >> 2) & 0x1)) 1200 o1z = 1; 1201 1202 if (is_addr_op) 1203 { 1204 if (unit_bit) 1205 base_unit = UNIT_A1; 1206 else 1207 base_unit = UNIT_A0; 1208 } 1209 else 1210 { 1211 if (unit_bit) 1212 base_unit = UNIT_D1; 1213 else 1214 base_unit = UNIT_D0; 1215 } 1216 1217 dest_no = (insn_word >> 19) & REG_MASK; 1218 src1_no = (insn_word >> 14) & REG_MASK; 1219 src2_no = (insn_word >> 9) & REG_MASK; 1220 1221 dest_unit = base_unit; 1222 1223 if (imm) 1224 { 1225 if (cond) 1226 { 1227 if (ca) 1228 { 1229 dest_unit = (insn_word >> 1) & UNIT_MASK; 1230 dest_reg = lookup_reg_name (dest_unit, dest_no); 1231 } 1232 else 1233 dest_reg = lookup_reg_name (dest_unit, dest_no); 1234 1235 src1_reg = lookup_reg_name (base_unit, src1_no); 1236 1237 value = (insn_word >> 6) & IMM8_MASK; 1238 1239 if (is_quickrot) 1240 { 1241 unsigned int qr_unit = unit_bit ? UNIT_A1 : UNIT_A0; 1242 unsigned int qr_no = 2; 1243 const char *qr_reg = lookup_reg_name (qr_unit, qr_no); 1244 1245 snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x,%s", dest_reg, 1246 src1_reg, value, qr_reg); 1247 } 1248 else 1249 snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg, 1250 src1_reg, value); 1251 } 1252 else 1253 { 1254 if (is_addr_op && (dest_no & ~CPC_REG_MASK)) 1255 { 1256 dest_reg = lookup_reg_name (dest_unit, dest_no & CPC_REG_MASK); 1257 src1_reg = lookup_reg_name (base_unit, 0x10); 1258 } 1259 else 1260 { 1261 dest_reg = lookup_reg_name (dest_unit, dest_no); 1262 src1_reg = lookup_reg_name (base_unit, dest_no); 1263 } 1264 1265 value = (insn_word >> 3) & IMM16_MASK; 1266 1267 if (se) 1268 { 1269 value = sign_extend (value, IMM16_BITS); 1270 if (o1z) 1271 { 1272 snprintf (buf, OPERAND_WIDTH, "%s,#%d", dest_reg, value); 1273 } 1274 else 1275 { 1276 snprintf (buf, OPERAND_WIDTH, "%s,%s,#%d", dest_reg, 1277 src1_reg, value); 1278 } 1279 } 1280 else 1281 { 1282 if (o1z) 1283 { 1284 snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value); 1285 } 1286 else 1287 { 1288 snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg, 1289 src1_reg, value); 1290 } 1291 } 1292 } 1293 } 1294 else 1295 { 1296 src1_reg = lookup_reg_name (base_unit, src1_no); 1297 1298 if (o2r) 1299 src2_reg = lookup_o2r (base_unit, src2_no); 1300 else 1301 src2_reg = lookup_reg_name (base_unit, src2_no); 1302 1303 if (cond) 1304 { 1305 dest_unit = (insn_word >> 5) & UNIT_MASK; 1306 1307 if (is_mul) 1308 { 1309 if (ca) 1310 dest_unit = (insn_word >> 1) & UNIT_MASK; 1311 else 1312 dest_unit = base_unit; 1313 } 1314 1315 dest_reg = lookup_reg_name (dest_unit, dest_no); 1316 1317 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, 1318 src1_reg, src2_reg); 1319 } 1320 else 1321 { 1322 dest_reg = lookup_reg_name (dest_unit, dest_no); 1323 1324 if (is_quickrot) 1325 { 1326 unsigned int qr_unit = unit_bit ? UNIT_A1 : UNIT_A0; 1327 unsigned int qr_no = 2 + ((insn_word >> 7) & 0x1); 1328 const char *qr_reg = lookup_reg_name (qr_unit, qr_no); 1329 1330 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s,%s", dest_reg, 1331 src1_reg, src2_reg, qr_reg); 1332 } 1333 else if (o1z) 1334 { 1335 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src2_reg); 1336 } 1337 else 1338 { 1339 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, 1340 src1_reg, src2_reg); 1341 } 1342 } 1343 } 1344 1345 if (dest_unit == UNIT_FX) 1346 print_insn (outf, "F", template->name, buf); 1347 else 1348 print_insn (outf, "", template->name, buf); 1349 } 1350 1351 /* Print a B instruction. */ 1352 static void 1353 print_branch (unsigned int insn_word, bfd_vma pc, 1354 const insn_template *template, 1355 disassemble_info *outf) 1356 { 1357 int value; 1358 1359 value = (insn_word >> 5) & IMM19_MASK; 1360 1361 value = sign_extend (value, IMM19_BITS); 1362 1363 value = value * 4; 1364 1365 value += pc; 1366 1367 print_insn (outf, "", template->name, ""); 1368 1369 outf->print_address_func (value, outf); 1370 } 1371 1372 /* Print a SWITCH instruction. */ 1373 static void 1374 print_switch (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1375 const insn_template *template, 1376 disassemble_info *outf) 1377 { 1378 char buf[OPERAND_WIDTH]; 1379 unsigned int value; 1380 1381 value = insn_word & IMM24_MASK; 1382 1383 snprintf (buf, OPERAND_WIDTH, "#%#x", value); 1384 1385 print_insn (outf, "", template->name, buf); 1386 } 1387 1388 /* Print a shift instruction. */ 1389 static void 1390 print_shift (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1391 const insn_template *template, 1392 disassemble_info *outf) 1393 { 1394 char buf[OPERAND_WIDTH]; 1395 unsigned int dest_no, src1_no, src2_no; 1396 unsigned int imm = (insn_word >> 25) & 0x1; 1397 unsigned int cond = (insn_word >> 26) & 0x1; 1398 unsigned int unit_bit = (insn_word >> 24) & 0x1; 1399 unsigned int ca = (insn_word >> 5) & 0x1; 1400 enum metag_unit base_unit; 1401 unsigned int dest_unit; 1402 const char *dest_reg; 1403 const char *src1_reg; 1404 const char *src2_reg; 1405 int value; 1406 1407 if (unit_bit) 1408 base_unit = UNIT_D1; 1409 else 1410 base_unit = UNIT_D0; 1411 1412 dest_no = (insn_word >> 19) & REG_MASK; 1413 src1_no = (insn_word >> 14) & REG_MASK; 1414 src2_no = (insn_word >> 9) & REG_MASK; 1415 1416 dest_unit = base_unit; 1417 1418 if (imm) 1419 { 1420 if (cond && ca) 1421 dest_unit = (insn_word >> 1) & UNIT_MASK; 1422 1423 dest_reg = lookup_reg_name (dest_unit, dest_no); 1424 1425 src1_reg = lookup_reg_name (base_unit, src1_no); 1426 1427 value = (insn_word >> 9) & IMM5_MASK; 1428 1429 snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg, 1430 src1_reg, value); 1431 } 1432 else 1433 { 1434 if (cond && ca) 1435 dest_unit = (insn_word >> 1) & UNIT_MASK; 1436 1437 dest_reg = lookup_reg_name (dest_unit, dest_no); 1438 1439 src1_reg = lookup_reg_name (base_unit, src1_no); 1440 src2_reg = lookup_reg_name (base_unit, src2_no); 1441 1442 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, 1443 src1_reg, src2_reg); 1444 } 1445 1446 if (dest_unit == UNIT_FX) 1447 print_insn (outf, "F", template->name, buf); 1448 else 1449 print_insn (outf, "", template->name, buf); 1450 } 1451 1452 /* Print a MIN or MAX instruction. */ 1453 static void 1454 print_min_max (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1455 const insn_template *template, 1456 disassemble_info *outf) 1457 { 1458 unsigned int base_unit, dest_no, src1_no, src2_no; 1459 char buf[OPERAND_WIDTH]; 1460 const char *dest_reg; 1461 const char *src1_reg; 1462 const char *src2_reg; 1463 1464 if ((insn_word >> 24) & UNIT_MASK) 1465 base_unit = UNIT_D1; 1466 else 1467 base_unit = UNIT_D0; 1468 1469 dest_no = (insn_word >> 19) & REG_MASK; 1470 src1_no = (insn_word >> 14) & REG_MASK; 1471 src2_no = (insn_word >> 9) & REG_MASK; 1472 1473 dest_reg = lookup_reg_name (base_unit, dest_no); 1474 1475 src1_reg = lookup_reg_name (base_unit, src1_no); 1476 src2_reg = lookup_reg_name (base_unit, src2_no); 1477 1478 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg); 1479 1480 print_insn (outf, "", template->name, buf); 1481 } 1482 1483 /* Print a bit operation instruction. */ 1484 static void 1485 print_bitop (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1486 const insn_template *template, 1487 disassemble_info *outf) 1488 { 1489 unsigned int swap_inst = MAJOR_OPCODE (template->meta_opcode) == OPC_MISC; 1490 unsigned int base_unit, src_unit, dest_no, src_no; 1491 unsigned int is_bexl = 0; 1492 char buf[OPERAND_WIDTH]; 1493 const char *dest_reg; 1494 const char *src_reg; 1495 1496 if (swap_inst && 1497 ((insn_word >> 1) & 0xb) == 0xa) 1498 is_bexl = 1; 1499 1500 if (swap_inst) 1501 { 1502 if (insn_word & 0x1) 1503 base_unit = UNIT_D1; 1504 else 1505 base_unit = UNIT_D0; 1506 } 1507 else 1508 { 1509 if ((insn_word >> 24) & 0x1) 1510 base_unit = UNIT_D1; 1511 else 1512 base_unit = UNIT_D0; 1513 } 1514 1515 src_unit = base_unit; 1516 1517 if (is_bexl) 1518 base_unit = get_pair_unit (base_unit); 1519 1520 dest_no = (insn_word >> 19) & REG_MASK; 1521 1522 dest_reg = lookup_reg_name (base_unit, dest_no); 1523 1524 src_no = (insn_word >> 14) & REG_MASK; 1525 1526 src_reg = lookup_reg_name (src_unit, src_no); 1527 1528 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 1529 1530 print_insn (outf, "", template->name, buf); 1531 } 1532 1533 /* Print a CMP or TST instruction. */ 1534 static void 1535 print_cmp (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1536 const insn_template *template, 1537 disassemble_info *outf) 1538 { 1539 char buf[OPERAND_WIDTH]; 1540 unsigned int dest_no, src_no; 1541 unsigned int imm = (insn_word >> 25) & 0x1; 1542 unsigned int cond = (insn_word >> 26) & 0x1; 1543 unsigned int o2r = insn_word & 0x1; 1544 unsigned int unit_bit = (insn_word >> 24) & 0x1; 1545 unsigned int se = (insn_word >> 1) & 0x1; 1546 enum metag_unit base_unit; 1547 const char *dest_reg; 1548 const char *src_reg; 1549 int value; 1550 1551 if (unit_bit) 1552 base_unit = UNIT_D1; 1553 else 1554 base_unit = UNIT_D0; 1555 1556 dest_no = (insn_word >> 14) & REG_MASK; 1557 src_no = (insn_word >> 9) & REG_MASK; 1558 1559 dest_reg = lookup_reg_name (base_unit, dest_no); 1560 1561 if (imm) 1562 { 1563 if (cond) 1564 { 1565 value = (insn_word >> 6) & IMM8_MASK; 1566 1567 snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value); 1568 } 1569 else 1570 { 1571 dest_no = (insn_word >> 19) & REG_MASK; 1572 1573 dest_reg = lookup_reg_name (base_unit, dest_no); 1574 1575 value = (insn_word >> 3) & IMM16_MASK; 1576 1577 if (se) 1578 { 1579 value = sign_extend (value, IMM16_BITS); 1580 snprintf (buf, OPERAND_WIDTH, "%s,#%d", dest_reg, value); 1581 } 1582 else 1583 { 1584 snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value); 1585 } 1586 } 1587 } 1588 else 1589 { 1590 if (o2r) 1591 src_reg = lookup_o2r (base_unit, src_no); 1592 else 1593 src_reg = lookup_reg_name (base_unit, src_no); 1594 1595 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 1596 } 1597 1598 print_insn (outf, "", template->name, buf); 1599 } 1600 1601 /* Print a CACHER instruction. */ 1602 static void 1603 print_cacher (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1604 const insn_template *template, 1605 disassemble_info *outf) 1606 { 1607 char buf[OPERAND_WIDTH]; 1608 char addr_buf[ADDR_WIDTH]; 1609 unsigned int reg_unit, reg_no; 1610 unsigned int size = ((insn_word >> 1) & 0x1) ? 8 : 4; 1611 const char *reg_name; 1612 const char *pair_name; 1613 1614 reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK); 1615 reg_no = (insn_word >> 19) & REG_MASK; 1616 1617 reg_name = lookup_reg_name (reg_unit, reg_no); 1618 pair_name = lookup_pair_reg_name (reg_unit, reg_no); 1619 1620 cache_addr_str (addr_buf, ADDR_WIDTH, insn_word, size); 1621 1622 if (size == 8) 1623 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name, pair_name, addr_buf); 1624 else 1625 snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf); 1626 1627 print_insn (outf, "", template->name, buf); 1628 } 1629 1630 /* Print a CACHEW instruction. */ 1631 static void 1632 print_cachew (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1633 const insn_template *template, 1634 disassemble_info *outf) 1635 { 1636 char buf[OPERAND_WIDTH]; 1637 char addr_buf[ADDR_WIDTH]; 1638 unsigned int reg_unit, reg_no; 1639 unsigned int size = ((insn_word >> 1) & 0x1) ? 8 : 4; 1640 const char *reg_name; 1641 const char *pair_name; 1642 1643 reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK); 1644 reg_no = (insn_word >> 19) & REG_MASK; 1645 1646 reg_name = lookup_reg_name (reg_unit, reg_no); 1647 pair_name = lookup_pair_reg_name (reg_unit, reg_no); 1648 1649 cache_addr_str (addr_buf, ADDR_WIDTH, insn_word, 64); 1650 1651 if (size == 8) 1652 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf, reg_name, pair_name); 1653 else 1654 snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name); 1655 1656 print_insn (outf, "", template->name, buf); 1657 } 1658 1659 /* Print an ICACHE instruction. */ 1660 static void 1661 print_icache (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1662 const insn_template *template, 1663 disassemble_info *outf) 1664 { 1665 char buf[OPERAND_WIDTH]; 1666 int offset; 1667 int pfcount; 1668 1669 offset = ((insn_word >> 9) & IMM15_MASK); 1670 pfcount = ((insn_word >> 1) & IMM4_MASK); 1671 1672 offset = sign_extend (offset, IMM15_BITS); 1673 1674 if (pfcount) 1675 snprintf (buf, OPERAND_WIDTH, "#%d,#0x%x", offset, pfcount); 1676 else 1677 snprintf (buf, OPERAND_WIDTH, "#%d,#0", offset); 1678 print_insn (outf, "", template->name, buf); 1679 } 1680 1681 /* Print a LNKGET instruction. */ 1682 static void 1683 print_lnkget (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1684 const insn_template *template, 1685 disassemble_info *outf) 1686 { 1687 char buf[OPERAND_WIDTH]; 1688 char addr_buf[ADDR_WIDTH]; 1689 unsigned int reg_unit, reg_no; 1690 unsigned int size = metag_get_set_ext_size_bytes (insn_word); 1691 const char *reg_name; 1692 const char *pair_name; 1693 1694 reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK); 1695 reg_no = (insn_word >> 19) & REG_MASK; 1696 1697 reg_name = lookup_reg_name (reg_unit, reg_no); 1698 pair_name = lookup_pair_reg_name (reg_unit, reg_no); 1699 1700 cache_addr_str (addr_buf, ADDR_WIDTH, insn_word, size); 1701 1702 if (size == 8) 1703 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name, pair_name, addr_buf); 1704 else 1705 snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf); 1706 1707 print_insn (outf, "", template->name, buf); 1708 } 1709 1710 /* Print an FPU MOV instruction. */ 1711 static void 1712 print_fmov (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1713 const insn_template *template, 1714 disassemble_info *outf) 1715 { 1716 char buf[OPERAND_WIDTH]; 1717 char prefix_buf[10]; 1718 unsigned int src_no, dest_no; 1719 unsigned int p = (insn_word >> 6) & 0x1; 1720 unsigned int d = (insn_word >> 5) & 0x1; 1721 unsigned int cc = (insn_word >> 1) & CC_MASK; 1722 bfd_boolean show_cond = cc != COND_A && cc != COND_NV; 1723 const char *dest_reg; 1724 const char *src_reg; 1725 const char *cc_flags; 1726 1727 dest_no = (insn_word >> 19) & REG_MASK; 1728 src_no = (insn_word >> 14) & REG_MASK; 1729 1730 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 1731 src_reg = lookup_reg_name (UNIT_FX, src_no); 1732 1733 cc_flags = lookup_fpu_scc_flags (cc); 1734 1735 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 1736 1737 snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "", 1738 d ? "D" : "", show_cond ? cc_flags : ""); 1739 1740 print_insn (outf, prefix_buf, template->name, buf); 1741 } 1742 1743 /* Convert an FPU rmask into a compatible form. */ 1744 static unsigned int 1745 convert_fx_rmask (unsigned int rmask) 1746 { 1747 int num_bits = hweight (rmask), i; 1748 unsigned int ret = 0; 1749 1750 for (i = 0; i < num_bits; i++) 1751 { 1752 ret <<= 1; 1753 ret |= 0x1; 1754 } 1755 1756 return ret; 1757 } 1758 1759 /* Print an FPU MMOV instruction. */ 1760 static void 1761 print_fmmov (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1762 const insn_template *template, 1763 disassemble_info *outf) 1764 { 1765 char buf[OPERAND_WIDTH]; 1766 char data_buf[REG_WIDTH]; 1767 char fpu_buf[REG_WIDTH]; 1768 bfd_boolean to_fpu = MAJOR_OPCODE (insn_word) == OPC_GET; 1769 bfd_boolean is_mmovl = MINOR_OPCODE (insn_word) & 0x1; 1770 unsigned int rmask = (insn_word >> 7) & RMASK_MASK; 1771 unsigned int fpu_no, data_no, data_unit; 1772 1773 data_no = (insn_word >> 19) & REG_MASK; 1774 fpu_no = (insn_word >> 14) & REG_MASK; 1775 1776 if (insn_word & 0x1) 1777 data_unit = UNIT_D1; 1778 else 1779 data_unit = UNIT_D0; 1780 1781 lookup_reg_list (data_buf, REG_WIDTH, data_unit, data_no, rmask, FALSE); 1782 lookup_reg_list (fpu_buf, REG_WIDTH, UNIT_FX, fpu_no, 1783 convert_fx_rmask (rmask), is_mmovl); 1784 1785 if (to_fpu) 1786 snprintf (buf, OPERAND_WIDTH, "%s,%s", fpu_buf, data_buf); 1787 else 1788 snprintf (buf, OPERAND_WIDTH, "%s,%s", data_buf, fpu_buf); 1789 1790 print_insn (outf, "F", template->name, buf); 1791 } 1792 1793 /* Print an FPU data unit MOV instruction. */ 1794 static void 1795 print_fmov_data (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1796 const insn_template *template, 1797 disassemble_info *outf) 1798 { 1799 char buf[OPERAND_WIDTH]; 1800 unsigned int src_no, dest_no; 1801 unsigned int to_fpu = ((insn_word >> 7) & 0x1); 1802 unsigned int unit_bit = (insn_word >> 24) & 0x1; 1803 enum metag_unit base_unit; 1804 const char *dest_reg; 1805 const char *src_reg; 1806 1807 dest_no = (insn_word >> 19) & REG_MASK; 1808 src_no = (insn_word >> 9) & REG_MASK; 1809 1810 if (unit_bit) 1811 base_unit = UNIT_D1; 1812 else 1813 base_unit = UNIT_D0; 1814 1815 if (to_fpu) 1816 { 1817 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 1818 src_reg = lookup_reg_name (base_unit, src_no); 1819 } 1820 else 1821 { 1822 dest_reg = lookup_reg_name (base_unit, dest_no); 1823 src_reg = lookup_reg_name (UNIT_FX, src_no); 1824 } 1825 1826 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 1827 1828 print_insn (outf, "F", template->name, buf); 1829 } 1830 1831 /* Print an FPU MOV immediate instruction. */ 1832 static void 1833 print_fmov_i (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1834 const insn_template *template, 1835 disassemble_info *outf) 1836 { 1837 char buf[OPERAND_WIDTH]; 1838 unsigned int dest_no; 1839 unsigned int p = (insn_word >> 2) & 0x1; 1840 unsigned int d = (insn_word >> 1) & 0x1; 1841 const char *dest_reg; 1842 unsigned int value = (insn_word >> 3) & IMM16_MASK; 1843 1844 dest_no = (insn_word >> 19) & REG_MASK; 1845 1846 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 1847 1848 snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value); 1849 1850 if (p) 1851 print_insn (outf, "FL", template->name, buf); 1852 else if (d) 1853 print_insn (outf, "FD", template->name, buf); 1854 else 1855 print_insn (outf, "F", template->name, buf); 1856 } 1857 1858 /* Print an FPU PACK instruction. */ 1859 static void 1860 print_fpack (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1861 const insn_template *template, 1862 disassemble_info *outf) 1863 { 1864 char buf[OPERAND_WIDTH]; 1865 unsigned int src1_no, src2_no, dest_no; 1866 const char *dest_reg; 1867 const char *src1_reg; 1868 const char *src2_reg; 1869 1870 dest_no = (insn_word >> 19) & REG_MASK; 1871 src1_no = (insn_word >> 14) & REG_MASK; 1872 src2_no = (insn_word >> 9) & REG_MASK; 1873 1874 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 1875 src1_reg = lookup_reg_name (UNIT_FX, src1_no); 1876 src2_reg = lookup_reg_name (UNIT_FX, src2_no); 1877 1878 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg); 1879 1880 print_insn (outf, "F", template->name, buf); 1881 } 1882 1883 /* Print an FPU SWAP instruction. */ 1884 static void 1885 print_fswap (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1886 const insn_template *template, 1887 disassemble_info *outf) 1888 { 1889 char buf[OPERAND_WIDTH]; 1890 unsigned int src_no, dest_no; 1891 const char *dest_reg; 1892 const char *src_reg; 1893 1894 dest_no = (insn_word >> 19) & REG_MASK; 1895 src_no = (insn_word >> 14) & REG_MASK; 1896 1897 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 1898 src_reg = lookup_reg_name (UNIT_FX, src_no); 1899 1900 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 1901 1902 print_insn (outf, "FL", template->name, buf); 1903 } 1904 1905 /* Print an FPU CMP instruction. */ 1906 static void 1907 print_fcmp (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1908 const insn_template *template, 1909 disassemble_info *outf) 1910 { 1911 char buf[OPERAND_WIDTH]; 1912 char prefix_buf[10]; 1913 unsigned int src_no, dest_no; 1914 unsigned int a = (insn_word >> 19) & 0x1; 1915 unsigned int z = (insn_word >> 8) & 0x1; 1916 unsigned int p = (insn_word >> 6) & 0x1; 1917 unsigned int d = (insn_word >> 5) & 0x1; 1918 unsigned int q = (insn_word >> 7) & 0x1; 1919 unsigned int cc = (insn_word >> 1) & CC_MASK; 1920 bfd_boolean show_cond = cc != COND_A && cc != COND_NV; 1921 const char *dest_reg; 1922 const char *src_reg; 1923 const char *cc_flags; 1924 1925 dest_no = (insn_word >> 14) & REG_MASK; 1926 src_no = (insn_word >> 9) & REG_MASK; 1927 1928 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 1929 src_reg = lookup_reg_name (UNIT_FX, src_no); 1930 1931 cc_flags = lookup_fpu_scc_flags (cc); 1932 1933 if (z) 1934 snprintf (buf, OPERAND_WIDTH, "%s,#0", dest_reg); 1935 else 1936 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 1937 1938 snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "", 1939 d ? "D" : "", a ? "A" : "", q ? "Q" : "", 1940 show_cond ? cc_flags : ""); 1941 1942 print_insn (outf, prefix_buf, template->name, buf); 1943 } 1944 1945 /* Print an FPU MIN or MAX instruction. */ 1946 static void 1947 print_fminmax (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1948 const insn_template *template, 1949 disassemble_info *outf) 1950 { 1951 char buf[OPERAND_WIDTH]; 1952 char prefix_buf[10]; 1953 unsigned int p = (insn_word >> 6) & 0x1; 1954 unsigned int d = (insn_word >> 5) & 0x1; 1955 unsigned int src1_no, src2_no, dest_no; 1956 unsigned int cc = (insn_word >> 1) & CC_MASK; 1957 bfd_boolean show_cond = cc != COND_A && cc != COND_NV; 1958 const char *dest_reg; 1959 const char *src1_reg; 1960 const char *src2_reg; 1961 const char *cc_flags; 1962 1963 dest_no = (insn_word >> 19) & REG_MASK; 1964 src1_no = (insn_word >> 14) & REG_MASK; 1965 src2_no = (insn_word >> 9) & REG_MASK; 1966 1967 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 1968 src1_reg = lookup_reg_name (UNIT_FX, src1_no); 1969 src2_reg = lookup_reg_name (UNIT_FX, src2_no); 1970 1971 cc_flags = lookup_fpu_scc_flags (cc); 1972 1973 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg); 1974 1975 snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "", 1976 d ? "D" : "", show_cond ? cc_flags : ""); 1977 1978 print_insn (outf, prefix_buf, template->name, buf); 1979 } 1980 1981 /* Print an FPU data conversion instruction. */ 1982 static void 1983 print_fconv (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 1984 const insn_template *template, 1985 disassemble_info *outf) 1986 { 1987 char buf[OPERAND_WIDTH]; 1988 char prefix_buf[10]; 1989 unsigned int p = (insn_word >> 6) & 0x1; 1990 unsigned int z = (insn_word >> 12) & 0x1; 1991 unsigned int src_no, dest_no; 1992 unsigned int cc = (insn_word >> 1) & CC_MASK; 1993 bfd_boolean show_cond = cc != COND_A && cc != COND_NV; 1994 const char *dest_reg; 1995 const char *src_reg; 1996 const char *cc_flags; 1997 1998 dest_no = (insn_word >> 19) & REG_MASK; 1999 src_no = (insn_word >> 14) & REG_MASK; 2000 2001 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 2002 src_reg = lookup_reg_name (UNIT_FX, src_no); 2003 2004 cc_flags = lookup_fpu_scc_flags (cc); 2005 2006 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 2007 2008 snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "", 2009 z ? "Z" : "", show_cond ? cc_flags : ""); 2010 2011 print_insn (outf, prefix_buf, template->name, buf); 2012 } 2013 2014 /* Print an FPU extended data conversion instruction. */ 2015 static void 2016 print_fconvx (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 2017 const insn_template *template, 2018 disassemble_info *outf) 2019 { 2020 char buf[OPERAND_WIDTH]; 2021 char prefix_buf[10]; 2022 unsigned int p = (insn_word >> 6) & 0x1; 2023 unsigned int xl = (insn_word >> 7) & 0x1; 2024 unsigned int src_no, dest_no, fraction_bits; 2025 unsigned int cc = (insn_word >> 1) & CC_MASK; 2026 bfd_boolean show_cond = cc != COND_A && cc != COND_NV; 2027 const char *dest_reg; 2028 const char *src_reg; 2029 const char *cc_flags; 2030 2031 dest_no = (insn_word >> 19) & REG_MASK; 2032 src_no = (insn_word >> 14) & REG_MASK; 2033 2034 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 2035 src_reg = lookup_reg_name (UNIT_FX, src_no); 2036 2037 cc_flags = lookup_fpu_scc_flags (cc); 2038 2039 if (xl) 2040 fraction_bits = (insn_word >> 8) & IMM6_MASK; 2041 else 2042 fraction_bits = (insn_word >> 9) & IMM5_MASK; 2043 2044 snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg, src_reg, 2045 fraction_bits); 2046 2047 snprintf (prefix_buf, 10, "F%s%s", p ? "L" : "", 2048 show_cond ? cc_flags : ""); 2049 2050 print_insn (outf, prefix_buf, template->name, buf); 2051 } 2052 2053 /* Print an FPU basic arithmetic instruction. */ 2054 static void 2055 print_fbarith (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 2056 const insn_template *template, 2057 disassemble_info *outf) 2058 { 2059 char buf[OPERAND_WIDTH]; 2060 char prefix_buf[10]; 2061 unsigned int n = (insn_word >> 7) & 0x1; 2062 unsigned int p = (insn_word >> 6) & 0x1; 2063 unsigned int d = (insn_word >> 5) & 0x1; 2064 unsigned int src1_no, src2_no, dest_no; 2065 unsigned int cc = (insn_word >> 1) & CC_MASK; 2066 bfd_boolean show_cond = cc != COND_A && cc != COND_NV; 2067 const char *dest_reg; 2068 const char *src1_reg; 2069 const char *src2_reg; 2070 const char *cc_flags; 2071 2072 dest_no = (insn_word >> 19) & REG_MASK; 2073 src1_no = (insn_word >> 14) & REG_MASK; 2074 src2_no = (insn_word >> 9) & REG_MASK; 2075 2076 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 2077 src1_reg = lookup_reg_name (UNIT_FX, src1_no); 2078 src2_reg = lookup_reg_name (UNIT_FX, src2_no); 2079 2080 cc_flags = lookup_fpu_scc_flags (cc); 2081 2082 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg); 2083 2084 snprintf (prefix_buf, 10, "F%s%s%s%s", p ? "L" : "", 2085 d ? "D" : "", n ? "I" : "", show_cond ? cc_flags : ""); 2086 2087 print_insn (outf, prefix_buf, template->name, buf); 2088 } 2089 2090 /* Print an FPU extended arithmetic instruction. */ 2091 static void 2092 print_fearith (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 2093 const insn_template *template, 2094 disassemble_info *outf) 2095 { 2096 char buf[OPERAND_WIDTH]; 2097 char prefix_buf[10]; 2098 bfd_boolean is_muz = (MINOR_OPCODE (insn_word) == 0x6 && 2099 ((insn_word >> 4) & 0x1)); 2100 bfd_boolean is_mac = (MINOR_OPCODE (insn_word) == 0x6 && 2101 (insn_word & 0x1f) == 0); 2102 bfd_boolean is_maw = (MINOR_OPCODE (insn_word) == 0x6 && 2103 ((insn_word >> 3) & 0x1)); 2104 unsigned int o3o = insn_word & 0x1; 2105 unsigned int q = is_muz && ((insn_word >> 1) & 0x1); 2106 unsigned int n = (insn_word >> 7) & 0x1; 2107 unsigned int p = (insn_word >> 6) & 0x1; 2108 unsigned int d = (insn_word >> 5) & 0x1; 2109 unsigned int cc = (insn_word >> 1) & CC_MASK; 2110 bfd_boolean show_cond = (MINOR_OPCODE (insn_word) == 0x5 && cc != COND_A && 2111 cc != COND_NV); 2112 unsigned int src1_no, src2_no, dest_no; 2113 const char *dest_reg; 2114 const char *src1_reg; 2115 const char *src2_reg; 2116 const char *cc_flags; 2117 2118 dest_no = (insn_word >> 19) & REG_MASK; 2119 src1_no = (insn_word >> 14) & REG_MASK; 2120 src2_no = (insn_word >> 9) & REG_MASK; 2121 2122 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 2123 src1_reg = lookup_reg_name (UNIT_FX, src1_no); 2124 src2_reg = lookup_reg_name (UNIT_FX, src2_no); 2125 2126 cc_flags = lookup_fpu_scc_flags (cc); 2127 2128 if (is_mac) 2129 snprintf (buf, OPERAND_WIDTH, "ACF.0,%s,%s", src1_reg, src2_reg); 2130 else if (o3o && is_maw) 2131 snprintf (buf, OPERAND_WIDTH, "%s,%s", src1_reg, src2_reg); 2132 else 2133 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg); 2134 2135 snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "", 2136 d ? "D" : "", n ? "I" : "", q ? "Q" : "", 2137 show_cond ? cc_flags : ""); 2138 2139 print_insn (outf, prefix_buf, template->name, buf); 2140 } 2141 2142 /* Print an FPU RCP or RSQ instruction. */ 2143 static void 2144 print_frec (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 2145 const insn_template *template, 2146 disassemble_info *outf) 2147 { 2148 char buf[OPERAND_WIDTH]; 2149 char prefix_buf[10]; 2150 unsigned int z = (insn_word >> 10) & 0x1; 2151 unsigned int q = (insn_word >> 9) & 0x1; 2152 unsigned int n = (insn_word >> 7) & 0x1; 2153 unsigned int p = (insn_word >> 6) & 0x1; 2154 unsigned int d = (insn_word >> 5) & 0x1; 2155 unsigned int src_no, dest_no; 2156 const char *dest_reg; 2157 const char *src_reg; 2158 2159 dest_no = (insn_word >> 19) & REG_MASK; 2160 src_no = (insn_word >> 14) & REG_MASK; 2161 2162 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 2163 src_reg = lookup_reg_name (UNIT_FX, src_no); 2164 2165 snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg); 2166 2167 snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "", 2168 d ? "D" : "", n ? "I" : "", q ? "Q" : "", z ? "Z" : ""); 2169 2170 print_insn (outf, prefix_buf, template->name, buf); 2171 } 2172 2173 static void 2174 print_fsimd (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 2175 const insn_template *template, 2176 disassemble_info *outf) 2177 { 2178 char buf[OPERAND_WIDTH]; 2179 unsigned int n = (insn_word >> 7) & 0x1; 2180 unsigned int src1_no, src2_no, dest_no; 2181 const char *dest_reg; 2182 const char *src1_reg; 2183 const char *src2_reg; 2184 2185 dest_no = (insn_word >> 19) & REG_MASK; 2186 src1_no = (insn_word >> 14) & REG_MASK; 2187 src2_no = (insn_word >> 9) & REG_MASK; 2188 2189 dest_reg = lookup_reg_name (UNIT_FX, dest_no); 2190 src1_reg = lookup_reg_name (UNIT_FX, src1_no); 2191 src2_reg = lookup_reg_name (UNIT_FX, src2_no); 2192 2193 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg); 2194 2195 if (n) 2196 print_insn (outf, "FLI", template->name, buf); 2197 else 2198 print_insn (outf, "FL", template->name, buf); 2199 } 2200 2201 /* Print an FPU accumulator GET or SET instruction. */ 2202 static void 2203 print_fget_set_acf (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 2204 const insn_template *template, 2205 disassemble_info *outf) 2206 { 2207 bfd_boolean is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET; 2208 char buf[OPERAND_WIDTH]; 2209 char addr_buf[ADDR_WIDTH]; 2210 unsigned int part; 2211 const char *reg_name; 2212 2213 part = (insn_word >> 19) & ACF_PART_MASK; 2214 2215 reg_name = lookup_acf_name (part); 2216 2217 mget_mset_addr_str (addr_buf, ADDR_WIDTH, insn_word); 2218 2219 if (is_get) 2220 { 2221 snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf); 2222 } 2223 else 2224 { 2225 snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name); 2226 } 2227 print_insn (outf, "F", template->name, buf); 2228 } 2229 2230 /* Return the name of the DSP register or accumulator for NUM and UNIT. */ 2231 static const char * 2232 __lookup_dsp_name (unsigned int num, unsigned int unit) 2233 { 2234 size_t i; 2235 2236 for (i = 0; i < sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]); i++) 2237 { 2238 const metag_reg *reg = &metag_dsp_regtab[i]; 2239 2240 if (reg->no == num) 2241 { 2242 if ((reg->unit == UNIT_RAM_D0 || reg->unit == UNIT_ACC_D0) && 2243 unit == UNIT_D0) 2244 return reg->name; 2245 2246 if ((reg->unit == UNIT_RAM_D1 || reg->unit == UNIT_ACC_D1) && 2247 unit == UNIT_D1) 2248 return reg->name; 2249 } 2250 } 2251 return "?.?"; 2252 } 2253 2254 /* Return the name of the DSP register for NUM and UNIT. */ 2255 static const char * 2256 lookup_dsp_name (unsigned int num, unsigned int unit) 2257 { 2258 size_t i; 2259 2260 for (i = 0; i < sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]); i++) 2261 { 2262 const metag_reg *reg = &metag_dsp_regtab[i]; 2263 2264 if (reg->no == num && reg->unit == unit) 2265 return reg->name; 2266 } 2267 return "?.?"; 2268 } 2269 2270 /* Return the name of the DSP RAM register for NUM and UNIT. */ 2271 static const char * 2272 lookup_dspram_name (unsigned int num, unsigned int unit, bfd_boolean load) 2273 { 2274 size_t i, nentries; 2275 2276 nentries = sizeof(metag_dsp_tmpl_regtab[load])/sizeof(metag_dsp_tmpl_regtab[load][0]); 2277 2278 for (i = 0; i < nentries; i++) 2279 { 2280 const metag_reg *reg = &metag_dsp_tmpl_regtab[load][i]; 2281 2282 if (reg->no == num && reg->unit == unit) 2283 return reg->name; 2284 } 2285 return "?.?"; 2286 } 2287 2288 /* This lookup function looks up the corresponding name for a register 2289 number in a DSP instruction. SOURCE indicates whether this 2290 register is a source or destination operand. */ 2291 static const char * 2292 lookup_any_reg_name (unsigned int unit, unsigned int num, bfd_boolean source) 2293 { 2294 /* A register with the top bit set (5th bit) indicates a DSPRAM 2295 register. */ 2296 if (num > 15) 2297 { 2298 unsigned int dunit = (unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1; 2299 return lookup_dspram_name (num, dunit, source); 2300 } 2301 else 2302 return lookup_reg_name (unit, num); 2303 } 2304 2305 /* Return the DSP data unit for UNIT. */ 2306 static inline enum metag_unit 2307 dsp_data_unit_to_sym (unsigned int unit) 2308 { 2309 if (unit == 0) 2310 return UNIT_D0; 2311 else 2312 return UNIT_D1; 2313 } 2314 2315 /* Print a DSP GET or SET instruction. */ 2316 static void 2317 print_dget_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 2318 const insn_template *template, 2319 disassemble_info *outf) 2320 { 2321 bfd_boolean is_get = (template->meta_opcode & 0x100); 2322 char buf[OPERAND_WIDTH]; 2323 char addr_buf[ADDR_WIDTH]; 2324 char prefix[DSP_PREFIX_WIDTH]; 2325 unsigned int part; 2326 const char *reg_name[2]; 2327 bfd_boolean is_high = FALSE; 2328 bfd_boolean is_dual = (insn_word & 0x4); 2329 bfd_boolean is_template = (insn_word & 0x2); 2330 const char *base_reg = "?"; 2331 unsigned int addr_unit, base_no, unit; 2332 2333 unit = dsp_data_unit_to_sym (insn_word & 0x1); 2334 2335 /* Is this a load/store to a template table? */ 2336 if (is_template) 2337 { 2338 part = (insn_word >> 19) & 0x1f; 2339 reg_name[0] = lookup_dsp_name (part, UNIT_DT); 2340 } 2341 else 2342 { 2343 part = (insn_word >> 19) & REG_MASK; 2344 is_high = ((part & 0x18) == 0x18); 2345 2346 /* Strip bit high indicator. */ 2347 if (is_high) 2348 part &= 0x17; 2349 2350 reg_name[0] = __lookup_dsp_name (part, unit); 2351 2352 } 2353 2354 /* Is this a dual unit DSP operation? The modulo operator below 2355 makes sure that we print the Rd register in the correct order, 2356 e.g. because there's only one bit in the instruction for the Data 2357 Unit we have to work out what the other data unit number is. 2358 (there's only 2). */ 2359 if (is_dual) 2360 { 2361 unsigned int _unit = insn_word & 0x1; 2362 2363 _unit = ((_unit + 1) % 2); 2364 reg_name[1] = __lookup_dsp_name(part, dsp_data_unit_to_sym (_unit)); 2365 } 2366 else 2367 reg_name[1] = NULL; 2368 2369 addr_unit = ((insn_word >> 18) & 0x1); 2370 if (addr_unit == 0) 2371 addr_unit = UNIT_A0; 2372 else 2373 addr_unit = UNIT_A1; 2374 2375 base_no = (insn_word >> 14) & DSP_REG_MASK; 2376 2377 base_reg = lookup_reg_name (addr_unit, base_no); 2378 2379 /* Check if it's a post-increment/post-decrement. */ 2380 if (insn_word & 0x2000) 2381 { 2382 unsigned int imm = (insn_word >> 9) & DGET_SET_IMM_MASK; 2383 const char *post_op; 2384 2385 switch (imm) 2386 { 2387 case 0x1: 2388 post_op = "++"; 2389 break; 2390 case 0x3: 2391 post_op = "--"; 2392 break; 2393 default: 2394 post_op = ""; 2395 } 2396 2397 snprintf (addr_buf, ADDR_WIDTH, "[%s%s]", base_reg, post_op); 2398 } 2399 else 2400 { 2401 unsigned int offset_part = (insn_word >> 9) & DSP_REG_MASK; 2402 const char *offset_reg = lookup_reg_name (addr_unit, offset_part); 2403 2404 snprintf (addr_buf, ADDR_WIDTH, "[%s+%s++]", base_reg, offset_reg); 2405 } 2406 2407 if (is_get) 2408 { 2409 if (is_dual && !is_template) 2410 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name[0], 2411 reg_name[1], addr_buf); 2412 else 2413 snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name[0], addr_buf); 2414 } 2415 else 2416 { 2417 if (is_dual && !is_template) 2418 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf, 2419 reg_name[0], reg_name[1]); 2420 else 2421 snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name[0]); 2422 } 2423 2424 snprintf (prefix, DSP_PREFIX_WIDTH, "D%s", is_high ? "H" : ""); 2425 print_insn (outf, prefix, template->name, buf); 2426 } 2427 2428 /* Print a DSP template instruction. */ 2429 static void 2430 print_dtemplate (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 2431 const insn_template *template, 2432 disassemble_info *outf) 2433 { 2434 char buf[OPERAND_WIDTH]; 2435 char prefix[DSP_PREFIX_WIDTH]; 2436 unsigned int offset[4]; 2437 bfd_boolean is_half = (MINOR_OPCODE (insn_word) == 0x5); 2438 bfd_boolean daop_only = (MINOR_OPCODE (insn_word) == 0x3); 2439 2440 offset[0] = ((insn_word >> 19) & REG_MASK); 2441 offset[1] = ((insn_word >> 14) & REG_MASK); 2442 offset[2] = ((insn_word >> 9) & REG_MASK); 2443 offset[3] = ((insn_word >> 4) & REG_MASK); 2444 2445 if (daop_only) 2446 snprintf (buf, OPERAND_WIDTH, "#0x%x,#0x%x,#0x%x", offset[0], 2447 offset[1], offset[2]); 2448 else 2449 { 2450 snprintf (buf, OPERAND_WIDTH, "#0x%x,#0x%x,#0x%x,#0x%x", offset[0], 2451 offset[1], offset[2], offset[3]); 2452 } 2453 2454 snprintf (prefix, DSP_PREFIX_WIDTH, "D%s", is_half ? "H" : ""); 2455 print_insn (outf, prefix, template->name, buf); 2456 } 2457 2458 /* Format template definition from INSN_WORD into BUF. */ 2459 static void 2460 decode_template_definition(unsigned int insn_word, char *buf, size_t len) 2461 { 2462 bfd_boolean load = ((insn_word >> 13) & 0x1); 2463 bfd_boolean dspram = (((insn_word >> 17) & 0x3) == 0x3); 2464 const char *template[1]; 2465 unsigned int tidx = ((insn_word >> 9) & TEMPLATE_REGS_MASK); 2466 enum metag_unit au, ram_unit; 2467 unsigned int addr_reg_nums[2]; 2468 const char *addr_reg_names[2]; 2469 const char *post_op = ""; 2470 const char *join_op = ""; 2471 enum metag_unit data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0; 2472 2473 template[0] = lookup_dsp_name (tidx, UNIT_DT); 2474 2475 addr_reg_names[1] = ""; 2476 2477 if (dspram) 2478 { 2479 ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1; 2480 addr_reg_nums[0] = ((insn_word >> 19) & REG_MASK); 2481 addr_reg_names[0] = lookup_dspram_name (addr_reg_nums[0], 2482 ram_unit, load); 2483 } 2484 else 2485 { 2486 bfd_boolean im = (((insn_word >> 18) & 0x1) != 0); 2487 2488 au = (((insn_word >> 23) & 0x1) == 0) ? UNIT_A0 : UNIT_A1; 2489 addr_reg_nums[0] = ((insn_word >> 19) & DSP_REG_MASK); 2490 2491 addr_reg_names[0] = lookup_reg_name (au, addr_reg_nums[0]); 2492 2493 if (im) 2494 { 2495 unsigned int im_value = ((insn_word >> 14) & 0x3); 2496 2497 switch (im_value) 2498 { 2499 case 0x1: 2500 post_op = "++"; 2501 break; 2502 case 0x3: 2503 post_op = "--"; 2504 break; 2505 } 2506 } 2507 else 2508 { 2509 addr_reg_nums[1] = ((insn_word >> 14) & DSP_REG_MASK); 2510 addr_reg_names[1] = lookup_reg_name (au, addr_reg_nums[1]); 2511 join_op = "+"; 2512 post_op = "++"; 2513 } 2514 } 2515 2516 if (load) 2517 { 2518 len = snprintf (buf, len, " %s,[%s%s%s%s]", template[0], addr_reg_names[0], 2519 join_op, addr_reg_names[1], post_op); 2520 } 2521 else 2522 { 2523 len = snprintf (buf, len, " [%s%s%s%s],%s", addr_reg_names[0], join_op, 2524 addr_reg_names[1], post_op, template[0]); 2525 } 2526 } 2527 2528 /* Print a DSP ALU instruction. */ 2529 static void 2530 print_dalu (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED, 2531 const insn_template *template, 2532 disassemble_info *outf) 2533 { 2534 bfd_boolean is_dual = FALSE; 2535 unsigned int data_unit = (((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0); 2536 const char *reg_names[3]; 2537 unsigned int reg_nums[3]; 2538 bfd_boolean ac = ((insn_word >> 7) & 0x1); 2539 char buf[OPERAND_WIDTH]; 2540 char prefix[DSP_PREFIX_WIDTH]; 2541 size_t len; 2542 bfd_boolean is_mod = FALSE; 2543 bfd_boolean is_overflow = FALSE; 2544 unsigned int reg_brackets[3]; 2545 bfd_boolean is_w_mx = FALSE; 2546 bfd_boolean is_b_mx = FALSE; 2547 bfd_boolean imm = FALSE; 2548 bfd_boolean is_quickrot64 = FALSE; 2549 bfd_boolean conditional = FALSE; 2550 const char *cc_flags = NULL; 2551 bfd_boolean is_unsigned = FALSE; 2552 2553 memset (reg_brackets, 0, sizeof (reg_brackets)); 2554 2555 if (template->arg_type & DSP_ARGS_1) 2556 { 2557 bfd_boolean is_template = FALSE; 2558 const char *addr_reg = NULL; 2559 bfd_boolean qr = FALSE; 2560 bfd_boolean is_acc_add = FALSE; 2561 bfd_boolean is_acc_sub = FALSE; 2562 bfd_boolean is_acc_zero = FALSE; 2563 bfd_boolean is_split8 = (template->arg_type & DSP_ARGS_SPLIT8); 2564 2565 /* Read DU bit. */ 2566 data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0; 2567 2568 conditional = ((insn_word >> 24) & 0x4); 2569 2570 /* Templates can't be conditional. */ 2571 is_template = (((insn_word & 0x02000002) == 0x2) && !conditional); 2572 2573 if (is_split8) 2574 is_mod = (insn_word & 0x80); 2575 2576 if (template->arg_type & DSP_ARGS_QR) 2577 { 2578 if (!conditional) 2579 is_quickrot64 = ((insn_word >> 5) & 0x1); 2580 } 2581 2582 if (template->arg_type & DSP_ARGS_DACC) 2583 { 2584 is_mod = (insn_word & 0x8); 2585 is_unsigned = (insn_word & 0x40); 2586 } 2587 2588 if (is_template) 2589 { 2590 is_w_mx = (insn_word & 0x1); 2591 is_dual = ((insn_word >> 0x4) & 0x1); 2592 2593 /* De.r,Dx.r,De.r|ACe.r */ 2594 if (template->arg_type & DSP_ARGS_ACC2) 2595 { 2596 is_mod = (insn_word & 0x8); 2597 is_overflow = (insn_word & 0x20); 2598 } 2599 2600 /* ACe.e,ACx.r,ACo.e? */ 2601 if ((template->arg_type & DSP_ARGS_XACC) && 2602 (((insn_word >> 6) & 0x5) == 0x5)) 2603 { 2604 enum metag_unit ac_unit, ao_unit; 2605 2606 ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1; 2607 2608 if (ac_unit == UNIT_ACC_D0) 2609 ao_unit = UNIT_ACC_D1; 2610 else 2611 ao_unit = UNIT_ACC_D0; 2612 2613 reg_nums[1] = ((insn_word >> 19) & REG_MASK); 2614 2615 /* These are dummy arguments anyway so the register 2616 number does not matter. */ 2617 reg_names[0] = lookup_dsp_name (16, ac_unit); /* ACe.0 */ 2618 reg_names[1] = lookup_dsp_name (16, ac_unit); /* ACx.0 */ 2619 reg_names[2] = lookup_dsp_name (16, ao_unit); /* ACo.0 */ 2620 } 2621 else 2622 { 2623 /* De.r|ACe.r,Dx.r,De.r */ 2624 if (template->arg_type & DSP_ARGS_DACC && 2625 ((insn_word & 0x84) != 0)) 2626 { 2627 enum metag_unit ac_unit; 2628 2629 ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1; 2630 reg_names[0] = lookup_dsp_name (16, ac_unit); 2631 2632 is_acc_zero = ((insn_word & 0x84) == 0x04); 2633 is_acc_add = ((insn_word & 0x84) == 0x80); 2634 is_acc_sub = ((insn_word & 0x84) == 0x84); 2635 } 2636 else 2637 reg_names[0] = lookup_any_reg_name (data_unit, 0, FALSE); 2638 2639 /* These are dummy arguments anyway so the register 2640 number does not matter. */ 2641 reg_names[1] = lookup_any_reg_name (data_unit, 0, TRUE); 2642 2643 /* De.r,Dx.r,De.r|ACe.r */ 2644 if ((template->arg_type & DSP_ARGS_ACC2) && 2645 ((insn_word & 0x80) == 0x80)) 2646 { 2647 enum metag_unit ac_unit; 2648 2649 ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1; 2650 reg_names[2] = lookup_dsp_name (16, ac_unit); 2651 } 2652 /* Detection of QUICKRoT and accumulator usage uses the 2653 same bits. They are mutually exclusive. */ 2654 else if (ac && (template->arg_type & DSP_ARGS_ACC2)) 2655 { 2656 reg_nums[2] = ((insn_word >> 9) & REG_MASK); 2657 2658 if (data_unit == UNIT_D0) 2659 reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D0); 2660 else 2661 reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D1); 2662 } 2663 else 2664 { 2665 if ((template->arg_type & DSP_ARGS_QR) && 2666 ((insn_word & 0x40) == 0x40)) 2667 { 2668 enum metag_unit aunit; 2669 int reg_no; 2670 2671 if (conditional) 2672 reg_no = ((insn_word >> 5) & 0x1); 2673 else 2674 reg_no = ((insn_word >> 7) & 0x1); 2675 2676 aunit = (data_unit == UNIT_D0) ? UNIT_A0 : UNIT_A1; 2677 addr_reg = lookup_reg_name (aunit, reg_no + 2); 2678 2679 qr = TRUE; 2680 } 2681 2682 reg_names[2] = lookup_any_reg_name (data_unit, 0, TRUE); 2683 } 2684 } 2685 2686 if (qr) 2687 { 2688 len = snprintf (buf, OPERAND_WIDTH, "%s,%s,%s,%s", 2689 reg_names[0], reg_names[1], reg_names[2], 2690 addr_reg); 2691 } 2692 else 2693 { 2694 len = snprintf (buf, OPERAND_WIDTH, "%s,%s,%s%s%s", 2695 reg_names[0], reg_names[1], 2696 reg_brackets[2] ? "[" : "", 2697 reg_names[2], reg_brackets[2] ? "]" : ""); 2698 } 2699 2700 decode_template_definition (insn_word, buf + len, 2701 OPERAND_WIDTH - len); 2702 } 2703 else /* Not a template definiton. */ 2704 { 2705 reg_nums[0] = ((insn_word >> 19) & REG_MASK); 2706 reg_nums[1] = ((insn_word >> 14) & REG_MASK); 2707 reg_nums[2] = ((insn_word >> 9) & REG_MASK); 2708 2709 imm = (((insn_word >> 24) & 0x2) && (template->arg_type & DSP_ARGS_IMM)); 2710 2711 if (imm) 2712 is_dual = (insn_word & 0x4); 2713 else if (!conditional) 2714 is_dual = (insn_word & 0x10); 2715 else 2716 cc_flags = lookup_scc_flags ((insn_word >> 1) & CC_MASK); 2717 2718 /* De.r,Dx.r,De.r|ACe.r */ 2719 if (template->arg_type & DSP_ARGS_ACC2) 2720 { 2721 is_mod = (insn_word & 0x8); 2722 is_overflow = (insn_word & 0x20); 2723 } 2724 2725 if (template->arg_type & DSP_ARGS_SPLIT8) 2726 { 2727 is_overflow = (insn_word & 0x20); 2728 } 2729 2730 /* ACe.e,ACx.r,ACo.e? */ 2731 if ((template->arg_type & DSP_ARGS_XACC) && 2732 (((insn_word >> 6) & 0x5) == 0x5)) 2733 { 2734 enum metag_unit ac_unit, ao_unit; 2735 2736 ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1; 2737 2738 if (ac_unit == UNIT_ACC_D0) 2739 ao_unit = UNIT_ACC_D1; 2740 else 2741 ao_unit = UNIT_ACC_D0; 2742 2743 reg_nums[1] = ((insn_word >> 19) & REG_MASK); 2744 reg_names[0] = lookup_dsp_name (reg_nums[1], ac_unit); 2745 reg_names[1] = lookup_dsp_name (reg_nums[1], ac_unit); 2746 reg_names[2] = lookup_dsp_name (reg_nums[1], ao_unit); 2747 } 2748 else 2749 { 2750 bfd_boolean o2r = (insn_word & 0x1); 2751 2752 /* De.r|ACe.r,Dx.r,De.r */ 2753 if ((template->arg_type & DSP_ARGS_DACC) && 2754 ((insn_word & 0x84) != 0)) 2755 { 2756 enum metag_unit ac_unit; 2757 2758 ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1; 2759 reg_names[0] = lookup_dsp_name (reg_nums[0], ac_unit); 2760 2761 is_acc_zero = ((insn_word & 0x84) == 0x04); 2762 is_acc_add = ((insn_word & 0x84) == 0x80); 2763 is_acc_sub = ((insn_word & 0x84) == 0x84); 2764 } 2765 else if (conditional) 2766 { 2767 reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]); 2768 } 2769 else 2770 { 2771 reg_names[0] = lookup_any_reg_name (data_unit, 2772 reg_nums[0], FALSE); 2773 if (reg_nums[0] > 15) 2774 reg_brackets[0] = 1; 2775 } 2776 2777 if (imm) 2778 { 2779 reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[0], TRUE); 2780 2781 if (reg_brackets[0]) 2782 reg_brackets[1] = 1; 2783 } 2784 else 2785 { 2786 if (is_split8 && is_mod) 2787 { 2788 reg_names[1] = lookup_reg_name (data_unit, reg_nums[1]); 2789 } 2790 else 2791 { 2792 reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[1], TRUE); 2793 2794 if (reg_nums[1] > 15) 2795 reg_brackets[1] = 1; 2796 } 2797 } 2798 2799 /* Detection of QUICKRoT and accumulator usage uses the 2800 same bits. They are mutually exclusive. */ 2801 if (ac && (template->arg_type & DSP_ARGS_ACC2)) 2802 { 2803 if (data_unit == UNIT_D0) 2804 reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D0); 2805 else 2806 reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D1); 2807 } 2808 2809 else 2810 { 2811 if ((template->arg_type & DSP_ARGS_QR) && 2812 ((insn_word & 0x40) == 0x40)) 2813 { 2814 enum metag_unit aunit; 2815 int reg_no; 2816 2817 if (conditional) 2818 reg_no = ((insn_word >> 5) & 0x1); 2819 else 2820 reg_no = ((insn_word >> 7) & 0x1); 2821 2822 aunit = (data_unit == UNIT_D0) ? UNIT_A0 : UNIT_A1; 2823 addr_reg = lookup_reg_name (aunit, reg_no + 2); 2824 2825 qr = TRUE; 2826 } 2827 2828 if (o2r) 2829 reg_names[2] = lookup_o2r (data_unit, reg_nums[2]); 2830 else 2831 { 2832 /* Can't use a DSPRAM reg if both QD and L1 are 2833 set on a QUICKRoT instruction or if we're a 2834 split 8. */ 2835 if (((template->arg_type & DSP_ARGS_QR) 2836 && ((insn_word & 0x30) == 0x30 && !conditional)) || 2837 (is_split8 && is_mod)) 2838 reg_names[2] = lookup_reg_name (data_unit, reg_nums[2]); 2839 else 2840 { 2841 reg_names[2] = lookup_any_reg_name (data_unit, 2842 reg_nums[2], TRUE); 2843 if (reg_nums[2] > 15) 2844 reg_brackets[2] = 1; 2845 } 2846 } 2847 } 2848 } 2849 2850 if (qr) 2851 { 2852 len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s,%s", 2853 reg_brackets[0] ? "[" : "", 2854 reg_names[0], reg_brackets[0] ? "]" : "", 2855 reg_brackets[1] ? "[" : "", 2856 reg_names[1], reg_brackets[1] ? "]" : "", 2857 reg_brackets[2] ? "[" : "", 2858 reg_names[2], reg_brackets[2] ? "]" : "", 2859 addr_reg); 2860 } 2861 else 2862 { 2863 if (imm) 2864 { 2865 /* Conform to the embedded assembler's policy of 2866 printing negative numbers as decimal and positive 2867 as hex. */ 2868 int value = ((insn_word >> 3) & IMM16_MASK); 2869 2870 if ((value & 0x8000) || value == 0) 2871 { 2872 value = sign_extend (value, IMM16_BITS); 2873 len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%d", 2874 reg_brackets[0] ? "[" : "", 2875 reg_names[0], reg_brackets[0] ? "]" : "", 2876 reg_brackets[1] ? "[" : "", 2877 reg_names[1], reg_brackets[1] ? "]" : "", 2878 value); 2879 } 2880 else 2881 { 2882 len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%#x", 2883 reg_brackets[0] ? "[" : "", 2884 reg_names[0], reg_brackets[0] ? "]" : "", 2885 reg_brackets[1] ? "[" : "", 2886 reg_names[1], reg_brackets[1] ? "]" : "", 2887 value); 2888 } 2889 } 2890 else 2891 { 2892 len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s", 2893 reg_brackets[0] ? "[" : "", 2894 reg_names[0], reg_brackets[0] ? "]" : "", 2895 reg_brackets[1] ? "[" : "", reg_names[1], 2896 reg_brackets[1] ? "]" : "", 2897 reg_brackets[2] ? "[" : "", 2898 reg_names[2], reg_brackets[2] ? "]" : ""); 2899 } 2900 } 2901 } 2902 2903 snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s%s%s%s%s%s%s", 2904 cc_flags ? cc_flags : "", 2905 is_dual ? "L" : "", 2906 is_quickrot64 ? "Q" : "", 2907 is_unsigned ? "U" : "", 2908 is_mod ? "M" : "", 2909 is_acc_zero ? "Z" : "", 2910 is_acc_add ? "P" : "", is_acc_sub ? "N" : "", 2911 is_overflow ? "O" : "", 2912 is_w_mx ? "W" : "", 2913 is_b_mx ? "B" : "", 2914 is_template ? "T" : ""); 2915 } 2916 else if (template->arg_type & DSP_ARGS_2) /* Group 2. */ 2917 { 2918 bfd_boolean is_template; 2919 bfd_boolean o2r = FALSE; 2920 int major = MAJOR_OPCODE (template->meta_opcode); 2921 bfd_boolean is_neg_or_mov = (major == OPC_ADD || major == OPC_SUB); 2922 bfd_boolean is_cmp_tst = ((major == OPC_CMP) && 2923 ((insn_word & 0x0000002c) == 0)); 2924 bfd_boolean is_fpu_mov = template->insn_type == INSN_DSP_FPU; 2925 bfd_boolean to_fpu = (template->meta_opcode >> 7) & 0x1; 2926 2927 if (major == OPC_9) 2928 imm = (insn_word & 0x2); 2929 else if (template->arg_type & DSP_ARGS_IMM) 2930 imm = ((insn_word >> 25) & 0x1); 2931 2932 is_template = (((insn_word & 0x02000002) == 0x2) && 2933 major != OPC_9); 2934 2935 if (imm) 2936 is_dual = ((insn_word >> 0x2) & 0x1); 2937 else 2938 is_dual = ((insn_word >> 0x4) & 0x1); 2939 2940 /* MOV and XSD[BW] do not have o2r. */ 2941 if (major != OPC_9 && major != OPC_MISC) 2942 o2r = (insn_word & 0x1); 2943 2944 if (is_neg_or_mov) 2945 { 2946 is_mod = (insn_word & 0x8); 2947 is_overflow = (insn_word & 0x20); 2948 } 2949 2950 /* XSD */ 2951 if (major == OPC_MISC) 2952 data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0; 2953 else 2954 data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0; 2955 2956 /* Check for NEG,MOV,ABS,FFB, etc. */ 2957 if (is_neg_or_mov || !is_cmp_tst || imm || 2958 MAJOR_OPCODE (insn_word) == OPC_9 || 2959 MAJOR_OPCODE (insn_word) == OPC_MISC) 2960 reg_nums[0] = ((insn_word >> 19) & REG_MASK); 2961 else 2962 reg_nums[0] = ((insn_word >> 14) & REG_MASK); 2963 2964 if (is_template) 2965 { 2966 is_w_mx = (insn_word & 0x1); 2967 2968 /* These are dummy arguments anyway so the register number 2969 does not matter. */ 2970 if (is_fpu_mov) 2971 { 2972 if (to_fpu) 2973 { 2974 reg_names[0] = lookup_reg_name (UNIT_FX, 0); 2975 reg_names[1] = lookup_reg_name (data_unit, 0); 2976 } 2977 else 2978 { 2979 reg_names[0] = lookup_reg_name (data_unit, 0); 2980 reg_names[1] = lookup_reg_name (UNIT_FX, 0); 2981 } 2982 } 2983 else 2984 { 2985 reg_names[0] = lookup_reg_name (data_unit, 0); 2986 reg_names[1] = lookup_reg_name (data_unit, 0); 2987 } 2988 2989 len = snprintf (buf, OPERAND_WIDTH, "%s,%s", 2990 reg_names[0], reg_names[1]); 2991 2992 decode_template_definition (insn_word, buf + len, 2993 OPERAND_WIDTH - len); 2994 } 2995 else 2996 { 2997 if (imm) 2998 { 2999 /* Conform to the embedded assembler's policy of 3000 printing negative numbers as decimal and positive as 3001 hex. */ 3002 unsigned int value = ((insn_word >> 3) & IMM16_MASK); 3003 3004 if (major == OPC_9) 3005 { 3006 data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0; 3007 is_dual = (insn_word & 0x4); 3008 3009 reg_names[0] = __lookup_dsp_name (reg_nums[0], data_unit); 3010 } 3011 else 3012 { 3013 reg_names[0] = lookup_any_reg_name (data_unit, reg_nums[0], TRUE); 3014 if (reg_nums[0] > 15) 3015 reg_brackets[0] = 1; 3016 } 3017 3018 if ((value & 0x8000) || value == 0) 3019 { 3020 value = sign_extend (value, IMM16_BITS); 3021 snprintf (buf, OPERAND_WIDTH, "%s%s%s,#%d", 3022 reg_brackets[0] ? "[" : "", 3023 reg_names[0], reg_brackets[0] ? "]" : "", 3024 value); 3025 } 3026 else 3027 { 3028 snprintf (buf, OPERAND_WIDTH, "%s%s%s,#0x%x", 3029 reg_brackets[0] ? "[" : "", 3030 reg_names[0], reg_brackets[0] ? "]" : "", 3031 value); 3032 } 3033 } 3034 else 3035 { 3036 if (is_neg_or_mov || is_cmp_tst) 3037 reg_nums[1] = ((insn_word >> 9) & REG_MASK); 3038 else 3039 reg_nums[1] = ((insn_word >> 14) & REG_MASK); 3040 3041 if (major == OPC_9) 3042 { 3043 is_dual = (insn_word & 0x4); 3044 data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0; 3045 3046 if (MINOR_OPCODE (template->meta_opcode) == 0x1) 3047 reg_names[0] = __lookup_dsp_name (reg_nums[0], data_unit); 3048 else 3049 reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]); 3050 } 3051 else 3052 { 3053 unsigned int reg0_unit = data_unit; 3054 3055 if (is_fpu_mov && to_fpu) 3056 reg0_unit = UNIT_FX; 3057 3058 reg_names[0] = lookup_any_reg_name (reg0_unit, reg_nums[0], 3059 (!is_neg_or_mov && is_cmp_tst)); 3060 if (reg_nums[0] > 15) 3061 reg_brackets[0] = 1; 3062 } 3063 3064 if (o2r) 3065 reg_names[1] = lookup_o2r (data_unit, reg_nums[1]); 3066 else 3067 { 3068 /* Check for accumulator argument. */ 3069 if (is_neg_or_mov && ((insn_word & 0x80) == 0x80)) 3070 { 3071 if (data_unit == UNIT_D0) 3072 reg_names[1] = lookup_dsp_name (reg_nums[1], UNIT_ACC_D0); 3073 else 3074 reg_names[1] = lookup_dsp_name (reg_nums[1], UNIT_ACC_D1); 3075 } 3076 else 3077 { 3078 if (major == OPC_9) 3079 { 3080 if (MINOR_OPCODE (template->meta_opcode) == 0x1) 3081 { 3082 reg_names[1] = lookup_reg_name (data_unit, reg_nums[1]); 3083 } 3084 else 3085 { 3086 enum metag_unit u; 3087 3088 u = (insn_word & 0x1) ? UNIT_RAM_D1 : UNIT_RAM_D0; 3089 reg_names[1] = lookup_dsp_name (reg_nums[1], u); 3090 } 3091 } 3092 else 3093 { 3094 reg_names[1] = lookup_any_reg_name (data_unit, 3095 reg_nums[1], TRUE); 3096 if (reg_nums[1] > 15) 3097 reg_brackets[1] = 1; 3098 } 3099 } 3100 } 3101 3102 snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s", 3103 reg_brackets[0] ? "[" : "", reg_names[0], 3104 reg_brackets[0] ? "]" : "", 3105 reg_brackets[1] ? "[" : "", reg_names[1], 3106 reg_brackets[1] ? "]" : ""); 3107 } 3108 } 3109 3110 snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s", 3111 is_fpu_mov ? "F" : "", 3112 is_dual ? "L" : "", 3113 is_mod ? "M" : "", is_overflow ? "O" : "", 3114 is_w_mx ? "W" : "", 3115 is_template ? "T" : ""); 3116 } 3117 else /* Group 3. */ 3118 { 3119 /* If both the C and CA bits are set, then the Rd register can 3120 be in any unit. Figure out which unit from the Ud field. */ 3121 bfd_boolean all_units = (((insn_word) & 0x04000020) == 0x04000020); 3122 enum metag_unit ud_unit = ((insn_word >> 1) & UNIT_MASK); 3123 enum metag_unit ram_unit, acc_unit; 3124 bfd_boolean round = FALSE; 3125 bfd_boolean clamp9 = FALSE; 3126 bfd_boolean clamp8 = FALSE; 3127 bfd_boolean is_template = ((insn_word & 0x04000002) == 0x2); 3128 3129 imm = ((insn_word >> 25) & 0x1); 3130 ac = (insn_word & 0x1); 3131 3132 conditional = (MINOR_OPCODE (insn_word) & 0x4); 3133 3134 /* Check for conditional and not Condition Always. */ 3135 if (conditional && !(insn_word & 0x20)) 3136 cc_flags = lookup_scc_flags ((insn_word >> 1) & CC_MASK); 3137 else if (!(conditional && (insn_word & 0x20))) 3138 is_dual = ((insn_word >> 0x4) & 0x1); 3139 3140 /* Conditional instructions don't have the L1 or RSPP fields. */ 3141 if ((insn_word & 0x04000000) == 0) 3142 { 3143 round = (((insn_word >> 2) & 0x3) == 0x1); 3144 clamp9 = (((insn_word >> 2) & 0x3) == 0x2); 3145 clamp8 = (((insn_word >> 2) & 0x3) == 0x3); 3146 } 3147 3148 /* Read DU bit. */ 3149 data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0; 3150 reg_nums[0] = ((insn_word >> 19) & REG_MASK); 3151 reg_nums[1] = ((insn_word >> 14) & REG_MASK); 3152 3153 ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1; 3154 acc_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1; 3155 3156 if (all_units) 3157 reg_names[0] = lookup_reg_name (ud_unit, reg_nums[0]); 3158 else 3159 { 3160 if (conditional) 3161 reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]); 3162 else 3163 { 3164 reg_names[0] = lookup_any_reg_name (data_unit, reg_nums[0], FALSE); 3165 if (reg_nums[0] > 15) 3166 reg_brackets[0] = 1; 3167 } 3168 } 3169 3170 if (ac) 3171 { 3172 reg_names[1] = lookup_dsp_name (reg_nums[1], acc_unit); 3173 } 3174 else 3175 { 3176 reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[1], TRUE); 3177 if (reg_nums[1] > 15) 3178 reg_brackets[1] = 1; 3179 } 3180 3181 if (imm) 3182 { 3183 snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%#x", 3184 reg_brackets[0] ? "[" : "", 3185 reg_names[0], reg_brackets[0] ? "]" : "", 3186 reg_brackets[1] ? "[" : "", 3187 reg_names[1], reg_brackets[1] ? "]" : "", 3188 ((insn_word >> 9) & IMM5_MASK)); 3189 } 3190 else 3191 { 3192 reg_nums[2] = ((insn_word >> 9) & REG_MASK); 3193 3194 reg_names[2] = lookup_any_reg_name (data_unit, reg_nums[2], TRUE); 3195 3196 if (reg_nums[2] > 15) 3197 reg_brackets[2] = 1; 3198 3199 if (is_template) 3200 { 3201 bfd_boolean load = ((insn_word >> 13) & 0x1); 3202 bfd_boolean dspram = (((insn_word >> 17) & 0x3) == 0x3); 3203 const char *tname[1]; 3204 unsigned int tidx = ((insn_word >> 9) & TEMPLATE_REGS_MASK); 3205 enum metag_unit au; 3206 unsigned int addr_reg_nums[2]; 3207 const char *addr_reg_names[2]; 3208 const char *post_op = ""; 3209 const char *join_op = ""; 3210 3211 is_w_mx = ((insn_word >> 5) & 0x1); 3212 3213 tname[0] = lookup_dsp_name (tidx, UNIT_DT); 3214 3215 /* These are dummy arguments anyway */ 3216 reg_names[0] = lookup_reg_name (data_unit, 0); 3217 if (ac) 3218 reg_names[1] = lookup_dsp_name (16, acc_unit); 3219 else 3220 reg_names[1] = lookup_reg_name (data_unit, 0); 3221 reg_names[2] = lookup_reg_name (data_unit, 0); 3222 3223 addr_reg_names[1] = ""; 3224 3225 if (dspram) 3226 { 3227 ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1; 3228 addr_reg_nums[0] = ((insn_word >> 19) & REG_MASK); 3229 addr_reg_names[0] = lookup_dspram_name (addr_reg_nums[0], 3230 ram_unit, load); 3231 } 3232 else 3233 { 3234 bfd_boolean im = (((insn_word >> 18) & 0x1) != 0); 3235 3236 au = (((insn_word >> 23) & 0x1) == 0) ? UNIT_A0 : UNIT_A1; 3237 addr_reg_nums[0] = ((insn_word >> 19) & DSP_REG_MASK); 3238 3239 addr_reg_names[0] = lookup_reg_name (au, addr_reg_nums[0]); 3240 3241 if (im) 3242 { 3243 unsigned int im_value = ((insn_word >> 14) & 0x3); 3244 3245 switch (im_value) 3246 { 3247 case 0x1: 3248 post_op = "++"; 3249 break; 3250 case 0x3: 3251 post_op = "--"; 3252 break; 3253 } 3254 } 3255 else 3256 { 3257 addr_reg_nums[1] = ((insn_word >> 14) & DSP_REG_MASK); 3258 addr_reg_names[1] = lookup_reg_name (au, addr_reg_nums[1]); 3259 join_op = "+"; 3260 post_op = "++"; 3261 } 3262 } 3263 3264 if (load) 3265 { 3266 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s %s,[%s%s%s%s]", 3267 reg_names[0], reg_names[1], reg_names[2], 3268 tname[0], addr_reg_names[0], join_op, 3269 addr_reg_names[1], post_op); 3270 } 3271 else 3272 { 3273 snprintf (buf, OPERAND_WIDTH, "%s,%s,%s [%s%s%s%s],%s", 3274 reg_names[0], reg_names[1], reg_names[2], 3275 addr_reg_names[0], join_op, addr_reg_names[1], 3276 post_op, tname[0]); 3277 } 3278 } 3279 else 3280 { 3281 snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s", 3282 reg_brackets[0] ? "[" : "", 3283 reg_names[0], reg_brackets[0] ? "]" : "", 3284 reg_brackets[1] ? "[" : "", 3285 reg_names[1], reg_brackets[1] ? "]" : "", 3286 reg_brackets[2] ? "[" : "", 3287 reg_names[2], reg_brackets[2] ? "]" : ""); 3288 } 3289 } 3290 3291 snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s%s", 3292 cc_flags ? cc_flags : "", 3293 is_dual ? "L" : "", clamp9 ? "G" : "", 3294 clamp8 ? "B" : "", round ? "R" : "", 3295 is_w_mx ? "W" : "", 3296 is_template ? "T" : ""); 3297 } 3298 3299 print_insn (outf, prefix, template->name, buf); 3300 3301 } 3302 3303 typedef void (*insn_printer)(unsigned int, bfd_vma, const insn_template *, 3304 disassemble_info *); 3305 3306 /* Printer table. */ 3307 static const insn_printer insn_printers[ENC_MAX] = 3308 { 3309 [ENC_NONE] = print_none, 3310 [ENC_MOV_U2U] = print_mov_u2u, 3311 [ENC_MOV_PORT] = print_mov_port, 3312 [ENC_MMOV] = print_mmov, 3313 [ENC_MDRD] = print_mdrd, 3314 [ENC_MOVL_TTREC] = print_movl_ttrec, 3315 [ENC_GET_SET] = print_get_set, 3316 [ENC_GET_SET_EXT] = print_get_set_ext, 3317 [ENC_MGET_MSET] = print_mget_mset, 3318 [ENC_COND_SET] = print_cond_set, 3319 [ENC_XFR] = print_xfr, 3320 [ENC_MOV_CT] = print_mov_ct, 3321 [ENC_SWAP] = print_swap, 3322 [ENC_JUMP] = print_jump, 3323 [ENC_CALLR] = print_callr, 3324 [ENC_ALU] = print_alu, 3325 [ENC_SHIFT] = print_shift, 3326 [ENC_MIN_MAX] = print_min_max, 3327 [ENC_BITOP] = print_bitop, 3328 [ENC_CMP] = print_cmp, 3329 [ENC_BRANCH] = print_branch, 3330 [ENC_KICK] = print_mov_u2u, 3331 [ENC_SWITCH] = print_switch, 3332 [ENC_CACHER] = print_cacher, 3333 [ENC_CACHEW] = print_cachew, 3334 [ENC_ICACHE] = print_icache, 3335 [ENC_LNKGET] = print_lnkget, 3336 [ENC_FMOV] = print_fmov, 3337 [ENC_FMMOV] = print_fmmov, 3338 [ENC_FMOV_DATA] = print_fmov_data, 3339 [ENC_FMOV_I] = print_fmov_i, 3340 [ENC_FPACK] = print_fpack, 3341 [ENC_FSWAP] = print_fswap, 3342 [ENC_FCMP] = print_fcmp, 3343 [ENC_FMINMAX] = print_fminmax, 3344 [ENC_FCONV] = print_fconv, 3345 [ENC_FCONVX] = print_fconvx, 3346 [ENC_FBARITH] = print_fbarith, 3347 [ENC_FEARITH] = print_fearith, 3348 [ENC_FREC] = print_frec, 3349 [ENC_FSIMD] = print_fsimd, 3350 [ENC_FGET_SET_ACF] = print_fget_set_acf, 3351 [ENC_DGET_SET] = print_dget_set, 3352 [ENC_DTEMPLATE] = print_dtemplate, 3353 [ENC_DALU] = print_dalu, 3354 }; 3355 3356 /* Entry point for instruction printing. */ 3357 int 3358 print_insn_metag (bfd_vma pc, disassemble_info *outf) 3359 { 3360 bfd_byte buf[4]; 3361 unsigned int insn_word; 3362 size_t i; 3363 outf->bytes_per_chunk = 4; 3364 3365 (*outf->read_memory_func) (pc & ~0x03, buf, 4, outf); 3366 insn_word = bfd_getl32 (buf); 3367 3368 for (i = 0; i < sizeof(metag_optab)/sizeof(metag_optab[0]); i++) 3369 { 3370 const insn_template *template = &metag_optab[i]; 3371 3372 if ((insn_word & template->meta_mask) == template->meta_opcode) 3373 { 3374 enum insn_encoding encoding = template->encoding; 3375 insn_printer printer = insn_printers[encoding]; 3376 3377 if (printer) 3378 printer (insn_word, pc, template, outf); 3379 3380 return 4; 3381 } 3382 } 3383 3384 return 4; 3385 } 3386