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