1 /* Instruction printing code for the ARC. 2 Copyright (C) 1994-2024 Free Software Foundation, Inc. 3 4 Contributed by Claudiu Zissulescu (claziss@synopsys.com) 5 6 This file is part of libopcodes. 7 8 This library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3, or (at your option) 11 any later version. 12 13 It is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 16 License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 MA 02110-1301, USA. */ 22 23 #include "sysdep.h" 24 #include <stdio.h> 25 #include <assert.h> 26 #include "dis-asm.h" 27 #include "opcode/arc.h" 28 #include "elf/arc.h" 29 #include "arc-dis.h" 30 #include "arc-ext.h" 31 #include "elf-bfd.h" 32 #include "libiberty.h" 33 #include "opintl.h" 34 35 /* Structure used to iterate over, and extract the values for, operands of 36 an opcode. */ 37 38 struct arc_operand_iterator 39 { 40 /* The complete instruction value to extract operands from. */ 41 unsigned long long insn; 42 43 /* The LIMM if this is being tracked separately. This field is only 44 valid if we find the LIMM operand in the operand list. */ 45 unsigned limm; 46 47 /* The opcode this iterator is operating on. */ 48 const struct arc_opcode *opcode; 49 50 /* The index into the opcodes operand index list. */ 51 const unsigned char *opidx; 52 }; 53 54 /* A private data used by ARC decoder. */ 55 struct arc_disassemble_info 56 { 57 /* The current disassembled arc opcode. */ 58 const struct arc_opcode *opcode; 59 60 /* Instruction length w/o limm field. */ 61 unsigned insn_len; 62 63 /* TRUE if we have limm. */ 64 bool limm_p; 65 66 /* LIMM value, if exists. */ 67 unsigned limm; 68 69 /* Condition code, if exists. */ 70 unsigned condition_code; 71 72 /* Writeback mode. */ 73 unsigned writeback_mode; 74 75 /* Number of operands. */ 76 unsigned operands_count; 77 78 struct arc_insn_operand operands[MAX_INSN_ARGS]; 79 }; 80 81 /* Globals variables. */ 82 83 static const char * const regnames[64] = 84 { 85 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 86 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 87 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 88 "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink", 89 90 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", 91 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", 92 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", 93 "r56", "r57", "r58", "r59", "lp_count", "reserved", "LIMM", "pcl" 94 }; 95 96 static const char * const addrtypenames[ARC_NUM_ADDRTYPES] = 97 { 98 "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd", 99 "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd" 100 }; 101 102 static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1; 103 104 static const char * const addrtypeunknown = "unknown"; 105 106 /* This structure keeps track which instruction class(es) 107 should be ignored durring disassembling. */ 108 109 typedef struct skipclass 110 { 111 insn_class_t insn_class; 112 insn_subclass_t subclass; 113 struct skipclass *nxt; 114 } skipclass_t, *linkclass; 115 116 /* Intial classes of instructions to be consider first when 117 disassembling. */ 118 static linkclass decodelist = NULL; 119 120 /* ISA mask value enforced via disassembler info options. ARC_OPCODE_NONE 121 value means that no CPU is enforced. */ 122 123 static unsigned enforced_isa_mask = ARC_OPCODE_NONE; 124 125 /* True if we want to print using only hex numbers. */ 126 static bool print_hex = false; 127 128 /* Macros section. */ 129 130 #ifdef DEBUG 131 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args) 132 #else 133 # define pr_debug(fmt, args...) 134 #endif 135 136 #define ARRANGE_ENDIAN(info, buf) \ 137 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \ 138 : bfd_getb32 (buf)) 139 140 #define BITS(word,s,e) (((word) >> (s)) & ((1ull << ((e) - (s)) << 1) - 1)) 141 #define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31)) 142 143 /* Functions implementation. */ 144 145 /* Initialize private data. */ 146 static bool 147 init_arc_disasm_info (struct disassemble_info *info) 148 { 149 struct arc_disassemble_info *arc_infop 150 = calloc (1, sizeof (*arc_infop)); 151 152 if (arc_infop == NULL) 153 return false; 154 155 info->private_data = arc_infop; 156 return true; 157 } 158 159 /* Add a new element to the decode list. */ 160 161 static void 162 add_to_decodelist (insn_class_t insn_class, 163 insn_subclass_t subclass) 164 { 165 linkclass t = (linkclass) xmalloc (sizeof (skipclass_t)); 166 167 t->insn_class = insn_class; 168 t->subclass = subclass; 169 t->nxt = decodelist; 170 decodelist = t; 171 } 172 173 /* Return TRUE if we need to skip the opcode from being 174 disassembled. */ 175 176 static bool 177 skip_this_opcode (const struct arc_opcode *opcode) 178 { 179 linkclass t = decodelist; 180 181 /* Check opcode for major 0x06, return if it is not in. */ 182 if (arc_opcode_len (opcode) == 4 183 && (OPCODE_32BIT_INSN (opcode->opcode) != 0x06 184 /* Can be an APEX extensions. */ 185 && OPCODE_32BIT_INSN (opcode->opcode) != 0x07)) 186 return false; 187 188 /* or not a known truble class. */ 189 switch (opcode->insn_class) 190 { 191 case FLOAT: 192 case DSP: 193 case ARITH: 194 case MPY: 195 break; 196 default: 197 return false; 198 } 199 200 while (t != NULL) 201 { 202 if ((t->insn_class == opcode->insn_class) 203 && (t->subclass == opcode->subclass)) 204 return false; 205 t = t->nxt; 206 } 207 208 return true; 209 } 210 211 static bfd_vma 212 bfd_getm32 (unsigned int data) 213 { 214 bfd_vma value = 0; 215 216 value = ((data & 0xff00) | (data & 0xff)) << 16; 217 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16; 218 return value; 219 } 220 221 static bool 222 special_flag_p (const char *opname, 223 const char *flgname) 224 { 225 const struct arc_flag_special *flg_spec; 226 unsigned i, j, flgidx; 227 228 for (i = 0; i < arc_num_flag_special; i++) 229 { 230 flg_spec = &arc_flag_special_cases[i]; 231 232 if (strcmp (opname, flg_spec->name)) 233 continue; 234 235 /* Found potential special case instruction. */ 236 for (j=0;; ++j) 237 { 238 flgidx = flg_spec->flags[j]; 239 if (flgidx == 0) 240 break; /* End of the array. */ 241 242 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0) 243 return true; 244 } 245 } 246 return false; 247 } 248 249 /* Find opcode from ARC_TABLE given the instruction described by INSN and 250 INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */ 251 252 static const struct arc_opcode * 253 find_format_from_table (struct disassemble_info *info, 254 const struct arc_opcode *arc_table, 255 unsigned long long insn, 256 unsigned int insn_len, 257 unsigned isa_mask, 258 bool *has_limm, 259 bool overlaps) 260 { 261 unsigned int i = 0; 262 const struct arc_opcode *opcode = NULL; 263 const struct arc_opcode *t_op = NULL; 264 const unsigned char *opidx; 265 const unsigned char *flgidx; 266 bool warn_p = false; 267 268 do 269 { 270 bool invalid = false; 271 272 opcode = &arc_table[i++]; 273 274 if (!(opcode->cpu & isa_mask)) 275 continue; 276 277 if (arc_opcode_len (opcode) != (int) insn_len) 278 continue; 279 280 if ((insn & opcode->mask) != opcode->opcode) 281 continue; 282 283 *has_limm = false; 284 285 /* Possible candidate, check the operands. */ 286 for (opidx = opcode->operands; *opidx; opidx++) 287 { 288 int value, limmind; 289 const struct arc_operand *operand = &arc_operands[*opidx]; 290 291 if (operand->flags & ARC_OPERAND_FAKE) 292 continue; 293 294 if (operand->extract) 295 value = (*operand->extract) (insn, &invalid); 296 else 297 value = (insn >> operand->shift) & ((1ull << operand->bits) - 1); 298 299 /* Check for LIMM indicator. If it is there, then make sure 300 we pick the right format. */ 301 limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E; 302 if (operand->flags & ARC_OPERAND_IR 303 && !(operand->flags & ARC_OPERAND_LIMM)) 304 { 305 if ((value == 0x3E && insn_len == 4) 306 || (value == limmind && insn_len == 2)) 307 { 308 invalid = true; 309 break; 310 } 311 } 312 313 if (operand->flags & ARC_OPERAND_LIMM 314 && !(operand->flags & ARC_OPERAND_DUPLICATE)) 315 *has_limm = true; 316 } 317 318 /* Check the flags. */ 319 for (flgidx = opcode->flags; *flgidx; flgidx++) 320 { 321 /* Get a valid flag class. */ 322 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx]; 323 const unsigned *flgopridx; 324 int foundA = 0, foundB = 0; 325 unsigned int value; 326 327 /* Check first the extensions. */ 328 if (cl_flags->flag_class & F_CLASS_EXTEND) 329 { 330 value = (insn & 0x1F); 331 if (arcExtMap_condCodeName (value)) 332 continue; 333 } 334 335 /* Check for the implicit flags. */ 336 if (cl_flags->flag_class & F_CLASS_IMPLICIT) 337 continue; 338 339 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx) 340 { 341 const struct arc_flag_operand *flg_operand = 342 &arc_flag_operands[*flgopridx]; 343 344 value = (insn >> flg_operand->shift) 345 & ((1 << flg_operand->bits) - 1); 346 if (value == flg_operand->code) 347 foundA = 1; 348 if (value) 349 foundB = 1; 350 } 351 352 if (!foundA && foundB) 353 { 354 invalid = true; 355 break; 356 } 357 } 358 359 if (invalid) 360 continue; 361 362 if (insn_len == 4 363 && overlaps) 364 { 365 warn_p = true; 366 t_op = opcode; 367 if (skip_this_opcode (opcode)) 368 continue; 369 } 370 371 /* The instruction is valid. */ 372 return opcode; 373 } 374 while (opcode->mask); 375 376 if (warn_p) 377 { 378 info->fprintf_styled_func 379 (info->stream, dis_style_text, 380 _("\nWarning: disassembly may be wrong due to " 381 "guessed opcode class choice.\n" 382 "Use -M<class[,class]> to select the correct " 383 "opcode class(es).\n\t\t\t\t")); 384 return t_op; 385 } 386 387 return NULL; 388 } 389 390 /* Find opcode for INSN, trying various different sources. The instruction 391 length in INSN_LEN will be updated if the instruction requires a LIMM 392 extension. 393 394 A pointer to the opcode is placed into OPCODE_RESULT, and ITER is 395 initialised, ready to iterate over the operands of the found opcode. If 396 the found opcode requires a LIMM then the LIMM value will be loaded into a 397 field of ITER. 398 399 This function returns TRUE in almost all cases, FALSE is reserved to 400 indicate an error (failing to find an opcode is not an error) a returned 401 result of FALSE would indicate that the disassembler can't continue. 402 403 If no matching opcode is found then the returned result will be TRUE, the 404 value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and 405 INSN_LEN will be unchanged. 406 407 If a matching opcode is found, then the returned result will be TRUE, the 408 opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by 409 4 if the instruction requires a LIMM, and the LIMM value will have been 410 loaded into a field of ITER. Finally, ITER will have been initialised so 411 that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's 412 operands. */ 413 414 static bool 415 find_format (bfd_vma memaddr, 416 unsigned long long insn, 417 unsigned int * insn_len, 418 unsigned isa_mask, 419 struct disassemble_info * info, 420 const struct arc_opcode ** opcode_result, 421 struct arc_operand_iterator * iter) 422 { 423 const struct arc_opcode *opcode = NULL; 424 bool needs_limm = false; 425 const extInstruction_t *einsn, *i; 426 unsigned limm = 0; 427 struct arc_disassemble_info *arc_infop = info->private_data; 428 429 /* First, try the extension instructions. */ 430 if (*insn_len == 4) 431 { 432 einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn); 433 for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next) 434 { 435 const char *errmsg = NULL; 436 437 opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg); 438 if (opcode == NULL) 439 { 440 (*info->fprintf_styled_func) 441 (info->stream, dis_style_text, 442 _("An error occurred while generating " 443 "the extension instruction operations")); 444 *opcode_result = NULL; 445 return false; 446 } 447 448 opcode = find_format_from_table (info, opcode, insn, *insn_len, 449 isa_mask, &needs_limm, false); 450 } 451 } 452 453 /* Then, try finding the first match in the opcode table. */ 454 if (opcode == NULL) 455 opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len, 456 isa_mask, &needs_limm, true); 457 458 if (opcode != NULL && needs_limm) 459 { 460 bfd_byte buffer[4]; 461 int status; 462 463 status = (*info->read_memory_func) (memaddr + *insn_len, buffer, 464 4, info); 465 if (status != 0) 466 { 467 opcode = NULL; 468 } 469 else 470 { 471 limm = ARRANGE_ENDIAN (info, buffer); 472 *insn_len += 4; 473 } 474 } 475 476 if (opcode != NULL) 477 { 478 iter->insn = insn; 479 iter->limm = limm; 480 iter->opcode = opcode; 481 iter->opidx = opcode->operands; 482 } 483 484 *opcode_result = opcode; 485 486 /* Update private data. */ 487 arc_infop->opcode = opcode; 488 arc_infop->limm = limm; 489 arc_infop->limm_p = needs_limm; 490 491 return true; 492 } 493 494 static void 495 print_flags (const struct arc_opcode *opcode, 496 unsigned long long *insn, 497 struct disassemble_info *info) 498 { 499 const unsigned char *flgidx; 500 unsigned int value; 501 struct arc_disassemble_info *arc_infop = info->private_data; 502 503 /* Now extract and print the flags. */ 504 for (flgidx = opcode->flags; *flgidx; flgidx++) 505 { 506 /* Get a valid flag class. */ 507 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx]; 508 const unsigned *flgopridx; 509 510 /* Check first the extensions. */ 511 if (cl_flags->flag_class & F_CLASS_EXTEND) 512 { 513 const char *name; 514 value = (insn[0] & 0x1F); 515 516 name = arcExtMap_condCodeName (value); 517 if (name) 518 { 519 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, 520 ".%s", name); 521 continue; 522 } 523 } 524 525 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx) 526 { 527 const struct arc_flag_operand *flg_operand = 528 &arc_flag_operands[*flgopridx]; 529 530 /* Implicit flags are only used for the insn decoder. */ 531 if (cl_flags->flag_class & F_CLASS_IMPLICIT) 532 { 533 if (cl_flags->flag_class & F_CLASS_COND) 534 arc_infop->condition_code = flg_operand->code; 535 else if (cl_flags->flag_class & F_CLASS_WB) 536 arc_infop->writeback_mode = flg_operand->code; 537 else if (cl_flags->flag_class & F_CLASS_ZZ) 538 info->data_size = flg_operand->code; 539 continue; 540 } 541 542 if (!flg_operand->favail) 543 continue; 544 545 value = (insn[0] >> flg_operand->shift) 546 & ((1 << flg_operand->bits) - 1); 547 if (value == flg_operand->code) 548 { 549 /* FIXME!: print correctly nt/t flag. */ 550 if (!special_flag_p (opcode->name, flg_operand->name)) 551 (*info->fprintf_styled_func) (info->stream, 552 dis_style_mnemonic, "."); 553 else if (info->insn_type == dis_dref) 554 { 555 switch (flg_operand->name[0]) 556 { 557 case 'b': 558 info->data_size = 1; 559 break; 560 case 'h': 561 case 'w': 562 info->data_size = 2; 563 break; 564 default: 565 info->data_size = 4; 566 break; 567 } 568 } 569 if (flg_operand->name[0] == 'd' 570 && flg_operand->name[1] == 0) 571 info->branch_delay_insns = 1; 572 573 /* Check if it is a conditional flag. */ 574 if (cl_flags->flag_class & F_CLASS_COND) 575 { 576 if (info->insn_type == dis_jsr) 577 info->insn_type = dis_condjsr; 578 else if (info->insn_type == dis_branch) 579 info->insn_type = dis_condbranch; 580 arc_infop->condition_code = flg_operand->code; 581 } 582 583 /* Check for the write back modes. */ 584 if (cl_flags->flag_class & F_CLASS_WB) 585 arc_infop->writeback_mode = flg_operand->code; 586 587 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, 588 "%s", flg_operand->name); 589 } 590 } 591 } 592 } 593 594 static const char * 595 get_auxreg (const struct arc_opcode *opcode, 596 int value, 597 unsigned isa_mask) 598 { 599 const char *name; 600 unsigned int i; 601 const struct arc_aux_reg *auxr = &arc_aux_regs[0]; 602 603 if (opcode->insn_class != AUXREG) 604 return NULL; 605 606 name = arcExtMap_auxRegName (value); 607 if (name) 608 return name; 609 610 for (i = 0; i < arc_num_aux_regs; i++, auxr++) 611 { 612 if (!(auxr->cpu & isa_mask)) 613 continue; 614 615 if (auxr->subclass != NONE) 616 return NULL; 617 618 if (auxr->address == value) 619 return auxr->name; 620 } 621 return NULL; 622 } 623 624 /* Convert a value representing an address type to a string used to refer to 625 the address type in assembly code. */ 626 627 static const char * 628 get_addrtype (int value) 629 { 630 if (value < 0 || value > addrtypenames_max) 631 return addrtypeunknown; 632 633 return addrtypenames[value]; 634 } 635 636 /* Calculate the instruction length for an instruction starting with MSB 637 and LSB, the most and least significant byte. The ISA_MASK is used to 638 filter the instructions considered to only those that are part of the 639 current architecture. 640 641 The instruction lengths are calculated from the ARC_OPCODE table, and 642 cached for later use. */ 643 644 static unsigned int 645 arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info) 646 { 647 bfd_byte major_opcode = msb >> 3; 648 649 switch (info->mach) 650 { 651 case bfd_mach_arc_arc700: 652 /* The nps400 extension set requires this special casing of the 653 instruction length calculation. Right now this is not causing any 654 problems as none of the known extensions overlap in opcode space, 655 but, if they ever do then we might need to start carrying 656 information around in the elf about which extensions are in use. */ 657 if (major_opcode == 0xb) 658 { 659 bfd_byte minor_opcode = lsb & 0x1f; 660 661 if (minor_opcode < 4) 662 return 6; 663 else if (minor_opcode == 0x10 || minor_opcode == 0x11) 664 return 8; 665 } 666 if (major_opcode == 0xa) 667 { 668 return 8; 669 } 670 /* Fall through. */ 671 case bfd_mach_arc_arc600: 672 return (major_opcode > 0xb) ? 2 : 4; 673 break; 674 675 case bfd_mach_arc_arcv2: 676 return (major_opcode > 0x7) ? 2 : 4; 677 break; 678 679 default: 680 return 0; 681 } 682 } 683 684 /* Extract and return the value of OPERAND from the instruction whose value 685 is held in the array INSN. */ 686 687 static int 688 extract_operand_value (const struct arc_operand *operand, 689 unsigned long long insn, 690 unsigned limm) 691 { 692 int value; 693 694 /* Read the limm operand, if required. */ 695 if (operand->flags & ARC_OPERAND_LIMM) 696 /* The second part of the instruction value will have been loaded as 697 part of the find_format call made earlier. */ 698 value = limm; 699 else 700 { 701 if (operand->extract) 702 value = (*operand->extract) (insn, (bool *) NULL); 703 else 704 { 705 if (operand->flags & ARC_OPERAND_ALIGNED32) 706 { 707 value = (insn >> operand->shift) 708 & ((1 << (operand->bits - 2)) - 1); 709 value = value << 2; 710 } 711 else 712 { 713 value = (insn >> operand->shift) & ((1 << operand->bits) - 1); 714 } 715 if (operand->flags & ARC_OPERAND_SIGNED) 716 { 717 int signbit = 1 << (operand->bits - 1); 718 value = (value ^ signbit) - signbit; 719 } 720 } 721 } 722 723 return value; 724 } 725 726 /* Find the next operand, and the operands value from ITER. Return TRUE if 727 there is another operand, otherwise return FALSE. If there is an 728 operand returned then the operand is placed into OPERAND, and the value 729 into VALUE. If there is no operand returned then OPERAND and VALUE are 730 unchanged. */ 731 732 static bool 733 operand_iterator_next (struct arc_operand_iterator *iter, 734 const struct arc_operand **operand, 735 int *value) 736 { 737 if (*iter->opidx == 0) 738 { 739 *operand = NULL; 740 return false; 741 } 742 743 *operand = &arc_operands[*iter->opidx]; 744 *value = extract_operand_value (*operand, iter->insn, iter->limm); 745 iter->opidx++; 746 747 return true; 748 } 749 750 /* Helper for parsing the options. */ 751 752 static void 753 parse_option (const char *option) 754 { 755 if (disassembler_options_cmp (option, "dsp") == 0) 756 add_to_decodelist (DSP, NONE); 757 758 else if (disassembler_options_cmp (option, "spfp") == 0) 759 add_to_decodelist (FLOAT, SPX); 760 761 else if (disassembler_options_cmp (option, "dpfp") == 0) 762 add_to_decodelist (FLOAT, DPX); 763 764 else if (disassembler_options_cmp (option, "quarkse_em") == 0) 765 { 766 add_to_decodelist (FLOAT, DPX); 767 add_to_decodelist (FLOAT, SPX); 768 add_to_decodelist (FLOAT, QUARKSE1); 769 add_to_decodelist (FLOAT, QUARKSE2); 770 } 771 772 else if (disassembler_options_cmp (option, "fpuda") == 0) 773 add_to_decodelist (FLOAT, DPA); 774 775 else if (disassembler_options_cmp (option, "nps400") == 0) 776 { 777 add_to_decodelist (ACL, NPS400); 778 add_to_decodelist (ARITH, NPS400); 779 add_to_decodelist (BITOP, NPS400); 780 add_to_decodelist (BMU, NPS400); 781 add_to_decodelist (CONTROL, NPS400); 782 add_to_decodelist (DMA, NPS400); 783 add_to_decodelist (DPI, NPS400); 784 add_to_decodelist (MEMORY, NPS400); 785 add_to_decodelist (MISC, NPS400); 786 add_to_decodelist (NET, NPS400); 787 add_to_decodelist (PMU, NPS400); 788 add_to_decodelist (PROTOCOL_DECODE, NPS400); 789 add_to_decodelist (ULTRAIP, NPS400); 790 } 791 792 else if (disassembler_options_cmp (option, "fpus") == 0) 793 { 794 add_to_decodelist (FLOAT, SP); 795 add_to_decodelist (FLOAT, CVT); 796 } 797 798 else if (disassembler_options_cmp (option, "fpud") == 0) 799 { 800 add_to_decodelist (FLOAT, DP); 801 add_to_decodelist (FLOAT, CVT); 802 } 803 else if (startswith (option, "hex")) 804 print_hex = true; 805 else 806 /* xgettext:c-format */ 807 opcodes_error_handler (_("unrecognised disassembler option: %s"), option); 808 } 809 810 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA) \ 811 { #NAME, ARC_OPCODE_ARC600, "ARC600" } 812 #define ARC_CPU_TYPE_A7xx(NAME,EXTRA) \ 813 { #NAME, ARC_OPCODE_ARC700, "ARC700" } 814 #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA) \ 815 { #NAME, ARC_OPCODE_ARCv2EM, "ARC EM" } 816 #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA) \ 817 { #NAME, ARC_OPCODE_ARCv2HS, "ARC HS" } 818 #define ARC_CPU_TYPE_NONE \ 819 { 0, 0, 0 } 820 821 /* A table of CPU names and opcode sets. */ 822 static const struct cpu_type 823 { 824 const char *name; 825 unsigned flags; 826 const char *isa; 827 } 828 cpu_types[] = 829 { 830 #include "elf/arc-cpu.def" 831 }; 832 833 /* Helper for parsing the CPU options. Accept any of the ARC architectures 834 values. OPTION should be a value passed to cpu=. */ 835 836 static unsigned 837 parse_cpu_option (const char *option) 838 { 839 int i; 840 841 for (i = 0; cpu_types[i].name; ++i) 842 { 843 if (!disassembler_options_cmp (cpu_types[i].name, option)) 844 { 845 return cpu_types[i].flags; 846 } 847 } 848 849 /* xgettext:c-format */ 850 opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option); 851 return ARC_OPCODE_NONE; 852 } 853 854 /* Go over the options list and parse it. */ 855 856 static void 857 parse_disassembler_options (const char *options) 858 { 859 const char *option; 860 861 if (options == NULL) 862 return; 863 864 /* Disassembler might be reused for difference CPU's, and cpu option set for 865 the first one shouldn't be applied to second (which might not have 866 explicit cpu in its options. Therefore it is required to reset enforced 867 CPU when new options are being parsed. */ 868 enforced_isa_mask = ARC_OPCODE_NONE; 869 870 FOR_EACH_DISASSEMBLER_OPTION (option, options) 871 { 872 /* A CPU option? Cannot use STRING_COMMA_LEN because strncmp is also a 873 preprocessor macro. */ 874 if (strncmp (option, "cpu=", 4) == 0) 875 /* Strip leading `cpu=`. */ 876 enforced_isa_mask = parse_cpu_option (option + 4); 877 else 878 parse_option (option); 879 } 880 } 881 882 /* Return the instruction type for an instruction described by OPCODE. */ 883 884 static enum dis_insn_type 885 arc_opcode_to_insn_type (const struct arc_opcode *opcode) 886 { 887 enum dis_insn_type insn_type; 888 889 switch (opcode->insn_class) 890 { 891 case BRANCH: 892 case BBIT0: 893 case BBIT1: 894 case BI: 895 case BIH: 896 case BRCC: 897 case DBNZ: 898 case EI: 899 case JLI: 900 case JUMP: 901 case LOOP: 902 if (!strncmp (opcode->name, "bl", 2) 903 || !strncmp (opcode->name, "jl", 2)) 904 { 905 if (opcode->subclass == COND) 906 insn_type = dis_condjsr; 907 else 908 insn_type = dis_jsr; 909 } 910 else 911 { 912 if (opcode->subclass == COND) 913 insn_type = dis_condbranch; 914 else 915 insn_type = dis_branch; 916 } 917 break; 918 case LOAD: 919 case STORE: 920 case MEMORY: 921 case ENTER: 922 case PUSH: 923 case POP: 924 insn_type = dis_dref; 925 break; 926 case LEAVE: 927 insn_type = dis_branch; 928 break; 929 default: 930 insn_type = dis_nonbranch; 931 break; 932 } 933 934 return insn_type; 935 } 936 937 /* Disassemble ARC instructions. */ 938 939 static int 940 print_insn_arc (bfd_vma memaddr, 941 struct disassemble_info *info) 942 { 943 bfd_byte buffer[8]; 944 unsigned int highbyte, lowbyte; 945 int status; 946 unsigned int insn_len; 947 unsigned long long insn = 0; 948 unsigned isa_mask = ARC_OPCODE_NONE; 949 const struct arc_opcode *opcode; 950 bool need_comma; 951 bool open_braket; 952 int size; 953 const struct arc_operand *operand; 954 int value, vpcl; 955 struct arc_operand_iterator iter; 956 struct arc_disassemble_info *arc_infop; 957 bool rpcl = false, rset = false; 958 959 if (info->disassembler_options) 960 { 961 parse_disassembler_options (info->disassembler_options); 962 963 /* Avoid repeated parsing of the options. */ 964 info->disassembler_options = NULL; 965 } 966 967 if (info->private_data == NULL && !init_arc_disasm_info (info)) 968 return -1; 969 970 memset (&iter, 0, sizeof (iter)); 971 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0); 972 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1); 973 974 /* Figure out CPU type, unless it was enforced via disassembler options. */ 975 if (enforced_isa_mask == ARC_OPCODE_NONE) 976 { 977 Elf_Internal_Ehdr *header = NULL; 978 979 if (info->section && info->section->owner) 980 header = elf_elfheader (info->section->owner); 981 982 switch (info->mach) 983 { 984 case bfd_mach_arc_arc700: 985 isa_mask = ARC_OPCODE_ARC700; 986 break; 987 988 case bfd_mach_arc_arc600: 989 isa_mask = ARC_OPCODE_ARC600; 990 break; 991 992 case bfd_mach_arc_arcv2: 993 default: 994 isa_mask = ARC_OPCODE_ARCv2EM; 995 /* TODO: Perhaps remove definition of header since it is only used at 996 this location. */ 997 if (header != NULL 998 && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS) 999 isa_mask = ARC_OPCODE_ARCv2HS; 1000 break; 1001 } 1002 } 1003 else 1004 isa_mask = enforced_isa_mask; 1005 1006 if (isa_mask == ARC_OPCODE_ARCv2HS) 1007 { 1008 /* FPU instructions are not extensions for HS. */ 1009 add_to_decodelist (FLOAT, SP); 1010 add_to_decodelist (FLOAT, DP); 1011 add_to_decodelist (FLOAT, CVT); 1012 } 1013 1014 /* This variable may be set by the instruction decoder. It suggests 1015 the number of bytes objdump should display on a single line. If 1016 the instruction decoder sets this, it should always set it to 1017 the same value in order to get reasonable looking output. */ 1018 info->bytes_per_line = 8; 1019 1020 /* In the next lines, we set two info variables control the way 1021 objdump displays the raw data. For example, if bytes_per_line is 1022 8 and bytes_per_chunk is 4, the output will look like this: 1023 00: 00000000 00000000 1024 with the chunks displayed according to "display_endian". */ 1025 if (info->section 1026 && !(info->section->flags & SEC_CODE)) 1027 { 1028 /* This is not a CODE section. */ 1029 switch (info->section->size) 1030 { 1031 case 1: 1032 case 2: 1033 case 4: 1034 size = info->section->size; 1035 break; 1036 default: 1037 size = (info->section->size & 0x01) ? 1 : 4; 1038 break; 1039 } 1040 info->bytes_per_chunk = 1; 1041 info->display_endian = info->endian; 1042 } 1043 else 1044 { 1045 size = 2; 1046 info->bytes_per_chunk = 2; 1047 info->display_endian = info->endian; 1048 } 1049 1050 /* Read the insn into a host word. */ 1051 status = (*info->read_memory_func) (memaddr, buffer, size, info); 1052 1053 if (status != 0) 1054 { 1055 (*info->memory_error_func) (status, memaddr, info); 1056 return -1; 1057 } 1058 1059 if (info->section 1060 && !(info->section->flags & SEC_CODE)) 1061 { 1062 /* Data section. */ 1063 unsigned long data; 1064 1065 data = bfd_get_bits (buffer, size * 8, 1066 info->display_endian == BFD_ENDIAN_BIG); 1067 switch (size) 1068 { 1069 case 1: 1070 (*info->fprintf_styled_func) (info->stream, 1071 dis_style_assembler_directive, 1072 ".byte"); 1073 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1074 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1075 "0x%02lx", data); 1076 break; 1077 case 2: 1078 (*info->fprintf_styled_func) (info->stream, 1079 dis_style_assembler_directive, 1080 ".short"); 1081 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1082 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1083 "0x%04lx", data); 1084 break; 1085 case 4: 1086 (*info->fprintf_styled_func) (info->stream, 1087 dis_style_assembler_directive, 1088 ".word"); 1089 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1090 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1091 "0x%08lx", data); 1092 break; 1093 default: 1094 return -1; 1095 } 1096 return size; 1097 } 1098 1099 insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info); 1100 pr_debug ("instruction length = %d bytes\n", insn_len); 1101 if (insn_len == 0) 1102 return -1; 1103 1104 arc_infop = info->private_data; 1105 arc_infop->insn_len = insn_len; 1106 1107 switch (insn_len) 1108 { 1109 case 2: 1110 insn = (buffer[highbyte] << 8) | buffer[lowbyte]; 1111 break; 1112 1113 case 4: 1114 { 1115 /* This is a long instruction: Read the remaning 2 bytes. */ 1116 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info); 1117 if (status != 0) 1118 { 1119 (*info->memory_error_func) (status, memaddr + 2, info); 1120 return -1; 1121 } 1122 insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer); 1123 } 1124 break; 1125 1126 case 6: 1127 { 1128 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info); 1129 if (status != 0) 1130 { 1131 (*info->memory_error_func) (status, memaddr + 2, info); 1132 return -1; 1133 } 1134 insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]); 1135 insn |= ((unsigned long long) buffer[highbyte] << 40) 1136 | ((unsigned long long) buffer[lowbyte] << 32); 1137 } 1138 break; 1139 1140 case 8: 1141 { 1142 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info); 1143 if (status != 0) 1144 { 1145 (*info->memory_error_func) (status, memaddr + 2, info); 1146 return -1; 1147 } 1148 insn = 1149 ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32) 1150 | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4]))); 1151 } 1152 break; 1153 1154 default: 1155 /* There is no instruction whose length is not 2, 4, 6, or 8. */ 1156 return -1; 1157 } 1158 1159 pr_debug ("instruction value = %llx\n", insn); 1160 1161 /* Set some defaults for the insn info. */ 1162 info->insn_info_valid = 1; 1163 info->branch_delay_insns = 0; 1164 info->data_size = 4; 1165 info->insn_type = dis_nonbranch; 1166 info->target = 0; 1167 info->target2 = 0; 1168 1169 /* FIXME to be moved in dissasemble_init_for_target. */ 1170 info->disassembler_needs_relocs = true; 1171 1172 /* Find the first match in the opcode table. */ 1173 if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter)) 1174 return -1; 1175 1176 if (!opcode) 1177 { 1178 switch (insn_len) 1179 { 1180 case 2: 1181 (*info->fprintf_styled_func) (info->stream, 1182 dis_style_assembler_directive, 1183 ".short"); 1184 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1185 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1186 "0x%04llx", insn & 0xffff); 1187 break; 1188 1189 case 4: 1190 (*info->fprintf_styled_func) (info->stream, 1191 dis_style_assembler_directive, 1192 ".word"); 1193 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1194 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1195 "0x%08llx", insn & 0xffffffff); 1196 break; 1197 1198 case 6: 1199 (*info->fprintf_styled_func) (info->stream, 1200 dis_style_assembler_directive, 1201 ".long"); 1202 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1203 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1204 "0x%08llx", insn & 0xffffffff); 1205 (*info->fprintf_styled_func) (info->stream, dis_style_text, " "); 1206 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1207 "0x%04llx", (insn >> 32) & 0xffff); 1208 break; 1209 1210 case 8: 1211 (*info->fprintf_styled_func) (info->stream, 1212 dis_style_assembler_directive, 1213 ".long"); 1214 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1215 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1216 "0x%08llx", insn & 0xffffffff); 1217 (*info->fprintf_styled_func) (info->stream, dis_style_text, " "); 1218 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1219 "0x%08llx", (insn >> 32)); 1220 break; 1221 1222 default: 1223 return -1; 1224 } 1225 1226 info->insn_type = dis_noninsn; 1227 return insn_len; 1228 } 1229 1230 /* Print the mnemonic. */ 1231 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, 1232 "%s", opcode->name); 1233 1234 /* Preselect the insn class. */ 1235 info->insn_type = arc_opcode_to_insn_type (opcode); 1236 1237 pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode); 1238 1239 print_flags (opcode, &insn, info); 1240 1241 if (opcode->operands[0] != 0) 1242 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1243 1244 need_comma = false; 1245 open_braket = false; 1246 arc_infop->operands_count = 0; 1247 1248 /* Now extract and print the operands. */ 1249 operand = NULL; 1250 vpcl = 0; 1251 while (operand_iterator_next (&iter, &operand, &value)) 1252 { 1253 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET)) 1254 { 1255 (*info->fprintf_styled_func) (info->stream, dis_style_text, "]"); 1256 open_braket = false; 1257 continue; 1258 } 1259 1260 /* Only take input from real operands. */ 1261 if (ARC_OPERAND_IS_FAKE (operand)) 1262 continue; 1263 1264 if ((operand->flags & ARC_OPERAND_IGNORE) 1265 && (operand->flags & ARC_OPERAND_IR) 1266 && value == -1) 1267 continue; 1268 1269 if (operand->flags & ARC_OPERAND_COLON) 1270 { 1271 (*info->fprintf_styled_func) (info->stream, dis_style_text, ":"); 1272 continue; 1273 } 1274 1275 if (need_comma) 1276 (*info->fprintf_styled_func) (info->stream, dis_style_text,","); 1277 1278 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET)) 1279 { 1280 (*info->fprintf_styled_func) (info->stream, dis_style_text, "["); 1281 open_braket = true; 1282 need_comma = false; 1283 continue; 1284 } 1285 1286 need_comma = true; 1287 1288 if (operand->flags & ARC_OPERAND_PCREL) 1289 { 1290 rpcl = true; 1291 vpcl = value; 1292 rset = true; 1293 1294 info->target = (bfd_vma) (memaddr & ~3) + value; 1295 } 1296 else if (!(operand->flags & ARC_OPERAND_IR)) 1297 { 1298 vpcl = value; 1299 rset = true; 1300 } 1301 1302 /* Print the operand as directed by the flags. */ 1303 if (operand->flags & ARC_OPERAND_IR) 1304 { 1305 const char *rname; 1306 1307 assert (value >=0 && value < 64); 1308 rname = arcExtMap_coreRegName (value); 1309 if (!rname) 1310 rname = regnames[value]; 1311 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1312 "%s", rname); 1313 1314 /* Check if we have a double register to print. */ 1315 if (operand->flags & ARC_OPERAND_TRUNCATE) 1316 { 1317 if ((value & 0x01) == 0) 1318 { 1319 rname = arcExtMap_coreRegName (value + 1); 1320 if (!rname) 1321 rname = regnames[value + 1]; 1322 } 1323 else 1324 rname = _("\nWarning: illegal use of double register " 1325 "pair.\n"); 1326 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1327 "%s", rname); 1328 } 1329 if (value == 63) 1330 rpcl = true; 1331 else 1332 rpcl = false; 1333 } 1334 else if (operand->flags & ARC_OPERAND_LIMM) 1335 { 1336 const char *rname = get_auxreg (opcode, value, isa_mask); 1337 1338 if (rname && open_braket) 1339 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1340 "%s", rname); 1341 else 1342 { 1343 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1344 "%#x", value); 1345 if (info->insn_type == dis_branch 1346 || info->insn_type == dis_jsr) 1347 info->target = (bfd_vma) value; 1348 } 1349 } 1350 else if (operand->flags & ARC_OPERAND_SIGNED) 1351 { 1352 const char *rname = get_auxreg (opcode, value, isa_mask); 1353 if (rname && open_braket) 1354 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1355 "%s", rname); 1356 else 1357 { 1358 if (print_hex) 1359 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1360 "%#x", value); 1361 else 1362 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1363 "%d", value); 1364 } 1365 } 1366 else if (operand->flags & ARC_OPERAND_ADDRTYPE) 1367 { 1368 const char *addrtype = get_addrtype (value); 1369 (*info->fprintf_styled_func) (info->stream, dis_style_address, 1370 "%s", addrtype); 1371 /* A colon follow an address type. */ 1372 need_comma = false; 1373 } 1374 else 1375 { 1376 if (operand->flags & ARC_OPERAND_TRUNCATE 1377 && !(operand->flags & ARC_OPERAND_ALIGNED32) 1378 && !(operand->flags & ARC_OPERAND_ALIGNED16) 1379 && value >= 0 && value <= 14) 1380 { 1381 /* Leave/Enter mnemonics. */ 1382 switch (value) 1383 { 1384 case 0: 1385 need_comma = false; 1386 break; 1387 case 1: 1388 (*info->fprintf_styled_func) (info->stream, 1389 dis_style_register, "r13"); 1390 break; 1391 default: 1392 (*info->fprintf_styled_func) (info->stream, 1393 dis_style_register, "r13"); 1394 (*info->fprintf_styled_func) (info->stream, 1395 dis_style_text, "-"); 1396 (*info->fprintf_styled_func) (info->stream, 1397 dis_style_register, "%s", 1398 regnames[13 + value - 1]); 1399 break; 1400 } 1401 rpcl = false; 1402 rset = false; 1403 } 1404 else 1405 { 1406 const char *rname = get_auxreg (opcode, value, isa_mask); 1407 if (rname && open_braket) 1408 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1409 "%s", rname); 1410 else 1411 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1412 "%#x", value); 1413 } 1414 } 1415 1416 if (operand->flags & ARC_OPERAND_LIMM) 1417 { 1418 arc_infop->operands[arc_infop->operands_count].kind 1419 = ARC_OPERAND_KIND_LIMM; 1420 /* It is not important to have exactly the LIMM indicator 1421 here. */ 1422 arc_infop->operands[arc_infop->operands_count].value = 63; 1423 } 1424 else 1425 { 1426 arc_infop->operands[arc_infop->operands_count].value = value; 1427 arc_infop->operands[arc_infop->operands_count].kind 1428 = (operand->flags & ARC_OPERAND_IR 1429 ? ARC_OPERAND_KIND_REG 1430 : ARC_OPERAND_KIND_SHIMM); 1431 } 1432 arc_infop->operands_count ++; 1433 } 1434 1435 /* Pretty print extra info for pc-relative operands. */ 1436 if (rpcl && rset) 1437 { 1438 if (info->flags & INSN_HAS_RELOC) 1439 /* If the instruction has a reloc associated with it, then the 1440 offset field in the instruction will actually be the addend 1441 for the reloc. (We are using REL type relocs). In such 1442 cases, we can ignore the pc when computing addresses, since 1443 the addend is not currently pc-relative. */ 1444 memaddr = 0; 1445 1446 (*info->fprintf_styled_func) (info->stream, 1447 dis_style_comment_start, "\t;"); 1448 (*info->print_address_func) ((memaddr & ~3) + vpcl, info); 1449 } 1450 1451 return insn_len; 1452 } 1453 1454 1455 disassembler_ftype 1456 arc_get_disassembler (bfd *abfd) 1457 { 1458 /* BFD my be absent, if opcodes is invoked from the debugger that 1459 has connected to remote target and doesn't have an ELF file. */ 1460 if (abfd != NULL) 1461 { 1462 /* Read the extension insns and registers, if any. */ 1463 build_ARC_extmap (abfd); 1464 #ifdef DEBUG 1465 dump_ARC_extmap (); 1466 #endif 1467 } 1468 1469 return print_insn_arc; 1470 } 1471 1472 /* Indices into option argument vector for options that do require 1473 an argument. Use ARC_OPTION_ARG_NONE for options that don't 1474 expect an argument. */ 1475 typedef enum 1476 { 1477 ARC_OPTION_ARG_NONE = -1, 1478 ARC_OPTION_ARG_ARCH, 1479 ARC_OPTION_ARG_SIZE 1480 } arc_option_arg_t; 1481 1482 /* Valid ARC disassembler options. */ 1483 static struct 1484 { 1485 const char *name; 1486 const char *description; 1487 arc_option_arg_t arg; 1488 } arc_options[] = 1489 { 1490 { "cpu=", N_("Enforce the designated architecture while decoding."), 1491 ARC_OPTION_ARG_ARCH }, 1492 { "dsp", N_("Recognize DSP instructions."), 1493 ARC_OPTION_ARG_NONE }, 1494 { "spfp", N_("Recognize FPX SP instructions."), 1495 ARC_OPTION_ARG_NONE }, 1496 { "dpfp", N_("Recognize FPX DP instructions."), 1497 ARC_OPTION_ARG_NONE }, 1498 { "quarkse_em", N_("Recognize FPU QuarkSE-EM instructions."), 1499 ARC_OPTION_ARG_NONE }, 1500 { "fpuda", N_("Recognize double assist FPU instructions."), 1501 ARC_OPTION_ARG_NONE }, 1502 { "fpus", N_("Recognize single precision FPU instructions."), 1503 ARC_OPTION_ARG_NONE }, 1504 { "fpud", N_("Recognize double precision FPU instructions."), 1505 ARC_OPTION_ARG_NONE }, 1506 { "nps400", N_("Recognize NPS400 instructions."), 1507 ARC_OPTION_ARG_NONE }, 1508 { "hex", N_("Use only hexadecimal number to print immediates."), 1509 ARC_OPTION_ARG_NONE } 1510 }; 1511 1512 /* Populate the structure for representing ARC's disassembly options. 1513 Such a dynamic initialization is desired, because it makes the maintenance 1514 easier and also gdb uses this to enable the "disassembler-option". */ 1515 1516 const disasm_options_and_args_t * 1517 disassembler_options_arc (void) 1518 { 1519 static disasm_options_and_args_t *opts_and_args; 1520 1521 if (opts_and_args == NULL) 1522 { 1523 disasm_option_arg_t *args; 1524 disasm_options_t *opts; 1525 size_t i; 1526 const size_t nr_of_options = ARRAY_SIZE (arc_options); 1527 /* There is a null element at the end of CPU_TYPES, therefore 1528 NR_OF_CPUS is actually 1 more and that is desired here too. */ 1529 const size_t nr_of_cpus = ARRAY_SIZE (cpu_types); 1530 1531 opts_and_args = XNEW (disasm_options_and_args_t); 1532 opts_and_args->args 1533 = XNEWVEC (disasm_option_arg_t, ARC_OPTION_ARG_SIZE + 1); 1534 opts_and_args->options.name 1535 = XNEWVEC (const char *, nr_of_options + 1); 1536 opts_and_args->options.description 1537 = XNEWVEC (const char *, nr_of_options + 1); 1538 opts_and_args->options.arg 1539 = XNEWVEC (const disasm_option_arg_t *, nr_of_options + 1); 1540 1541 /* Populate the arguments for "cpu=" option. */ 1542 args = opts_and_args->args; 1543 args[ARC_OPTION_ARG_ARCH].name = "ARCH"; 1544 args[ARC_OPTION_ARG_ARCH].values = XNEWVEC (const char *, nr_of_cpus); 1545 for (i = 0; i < nr_of_cpus; ++i) 1546 args[ARC_OPTION_ARG_ARCH].values[i] = cpu_types[i].name; 1547 args[ARC_OPTION_ARG_SIZE].name = NULL; 1548 args[ARC_OPTION_ARG_SIZE].values = NULL; 1549 1550 /* Populate the options. */ 1551 opts = &opts_and_args->options; 1552 for (i = 0; i < nr_of_options; ++i) 1553 { 1554 opts->name[i] = arc_options[i].name; 1555 opts->description[i] = arc_options[i].description; 1556 if (arc_options[i].arg != ARC_OPTION_ARG_NONE) 1557 opts->arg[i] = &args[arc_options[i].arg]; 1558 else 1559 opts->arg[i] = NULL; 1560 } 1561 opts->name[nr_of_options] = NULL; 1562 opts->description[nr_of_options] = NULL; 1563 opts->arg[nr_of_options] = NULL; 1564 } 1565 1566 return opts_and_args; 1567 } 1568 1569 1570 void 1571 print_arc_disassembler_options (FILE *stream) 1572 { 1573 const disasm_options_and_args_t *opts_and_args; 1574 const disasm_option_arg_t *args; 1575 const disasm_options_t *opts; 1576 size_t i, j; 1577 size_t max_len = 0; 1578 1579 opts_and_args = disassembler_options_arc (); 1580 opts = &opts_and_args->options; 1581 args = opts_and_args->args; 1582 1583 fprintf (stream, _("\nThe following ARC specific disassembler options are" 1584 " supported for use \nwith the -M switch (multiple" 1585 " options should be separated by commas):\n")); 1586 1587 /* Find the maximum length for printing options (and their arg name). */ 1588 for (i = 0; opts->name[i] != NULL; ++i) 1589 { 1590 size_t len = strlen (opts->name[i]); 1591 len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0; 1592 max_len = (len > max_len) ? len : max_len; 1593 } 1594 1595 /* Print the options, their arg and description, if any. */ 1596 for (i = 0, ++max_len; opts->name[i] != NULL; ++i) 1597 { 1598 fprintf (stream, " %s", opts->name[i]); 1599 if (opts->arg[i] != NULL) 1600 fprintf (stream, "%s", opts->arg[i]->name); 1601 if (opts->description[i] != NULL) 1602 { 1603 size_t len = strlen (opts->name[i]); 1604 len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0; 1605 fprintf (stream, 1606 "%*c %s", (int) (max_len - len), ' ', opts->description[i]); 1607 } 1608 fprintf (stream, _("\n")); 1609 } 1610 1611 /* Print the possible values of an argument. */ 1612 for (i = 0; args[i].name != NULL; ++i) 1613 { 1614 size_t len = 3; 1615 if (args[i].values == NULL) 1616 continue; 1617 fprintf (stream, _("\n\ 1618 For the options above, the following values are supported for \"%s\":\n "), 1619 args[i].name); 1620 for (j = 0; args[i].values[j] != NULL; ++j) 1621 { 1622 fprintf (stream, " %s", args[i].values[j]); 1623 len += strlen (args[i].values[j]) + 1; 1624 /* reset line if printed too long. */ 1625 if (len >= 78) 1626 { 1627 fprintf (stream, _("\n ")); 1628 len = 3; 1629 } 1630 } 1631 fprintf (stream, _("\n")); 1632 } 1633 1634 fprintf (stream, _("\n")); 1635 } 1636 1637 void arc_insn_decode (bfd_vma addr, 1638 struct disassemble_info *info, 1639 disassembler_ftype disasm_func, 1640 struct arc_instruction *insn) 1641 { 1642 const struct arc_opcode *opcode; 1643 struct arc_disassemble_info *arc_infop; 1644 1645 /* Ensure that insn would be in the reset state. */ 1646 memset (insn, 0, sizeof (struct arc_instruction)); 1647 1648 /* There was an error when disassembling, for example memory read error. */ 1649 if (disasm_func (addr, info) < 0) 1650 { 1651 insn->valid = false; 1652 return; 1653 } 1654 1655 assert (info->private_data != NULL); 1656 arc_infop = info->private_data; 1657 1658 insn->length = arc_infop->insn_len;; 1659 insn->address = addr; 1660 1661 /* Quick exit if memory at this address is not an instruction. */ 1662 if (info->insn_type == dis_noninsn) 1663 { 1664 insn->valid = false; 1665 return; 1666 } 1667 1668 insn->valid = true; 1669 1670 opcode = (const struct arc_opcode *) arc_infop->opcode; 1671 insn->insn_class = opcode->insn_class; 1672 insn->limm_value = arc_infop->limm; 1673 insn->limm_p = arc_infop->limm_p; 1674 1675 insn->is_control_flow = (info->insn_type == dis_branch 1676 || info->insn_type == dis_condbranch 1677 || info->insn_type == dis_jsr 1678 || info->insn_type == dis_condjsr); 1679 1680 insn->has_delay_slot = info->branch_delay_insns; 1681 insn->writeback_mode 1682 = (enum arc_ldst_writeback_mode) arc_infop->writeback_mode; 1683 insn->data_size_mode = info->data_size; 1684 insn->condition_code = arc_infop->condition_code; 1685 memcpy (insn->operands, arc_infop->operands, 1686 sizeof (struct arc_insn_operand) * MAX_INSN_ARGS); 1687 insn->operands_count = arc_infop->operands_count; 1688 } 1689 1690 /* Local variables: 1691 eval: (c-set-style "gnu") 1692 indent-tabs-mode: t 1693 End: */ 1694