1/* Instruction printing code for the ARC. 2 Copyright (C) 1994-2017 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 38struct 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/* Globals variables. */ 55 56static const char * const regnames[64] = 57{ 58 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 59 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 60 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 61 "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink", 62 63 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", 64 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", 65 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", 66 "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl" 67}; 68 69static const char * const addrtypenames[ARC_NUM_ADDRTYPES] = 70{ 71 "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd", 72 "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd" 73}; 74 75static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1; 76 77static const char * const addrtypeunknown = "unknown"; 78 79/* This structure keeps track which instruction class(es) 80 should be ignored durring disassembling. */ 81 82typedef struct skipclass 83{ 84 insn_class_t insn_class; 85 insn_subclass_t subclass; 86 struct skipclass *nxt; 87} skipclass_t, *linkclass; 88 89/* Intial classes of instructions to be consider first when 90 disassembling. */ 91static linkclass decodelist = NULL; 92 93/* Macros section. */ 94 95#ifdef DEBUG 96# define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args) 97#else 98# define pr_debug(fmt, args...) 99#endif 100 101#define ARRANGE_ENDIAN(info, buf) \ 102 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \ 103 : bfd_getb32 (buf)) 104 105#define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \ 106 (s + (sizeof (word) * 8 - 1 - e))) 107#define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31)) 108 109/* Functions implementation. */ 110 111/* Add a new element to the decode list. */ 112 113static void 114add_to_decodelist (insn_class_t insn_class, 115 insn_subclass_t subclass) 116{ 117 linkclass t = (linkclass) xmalloc (sizeof (skipclass_t)); 118 119 t->insn_class = insn_class; 120 t->subclass = subclass; 121 t->nxt = decodelist; 122 decodelist = t; 123} 124 125/* Return TRUE if we need to skip the opcode from being 126 disassembled. */ 127 128static bfd_boolean 129skip_this_opcode (const struct arc_opcode *opcode) 130{ 131 linkclass t = decodelist; 132 133 /* Check opcode for major 0x06, return if it is not in. */ 134 if (arc_opcode_len (opcode) == 4 135 && OPCODE_32BIT_INSN (opcode->opcode) != 0x06) 136 return FALSE; 137 138 /* or not a known truble class. */ 139 switch (opcode->insn_class) 140 { 141 case FLOAT: 142 case DSP: 143 break; 144 default: 145 return FALSE; 146 } 147 148 while (t != NULL) 149 { 150 if ((t->insn_class == opcode->insn_class) 151 && (t->subclass == opcode->subclass)) 152 return FALSE; 153 t = t->nxt; 154 } 155 156 return TRUE; 157} 158 159static bfd_vma 160bfd_getm32 (unsigned int data) 161{ 162 bfd_vma value = 0; 163 164 value = ((data & 0xff00) | (data & 0xff)) << 16; 165 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16; 166 return value; 167} 168 169static bfd_boolean 170special_flag_p (const char *opname, 171 const char *flgname) 172{ 173 const struct arc_flag_special *flg_spec; 174 unsigned i, j, flgidx; 175 176 for (i = 0; i < arc_num_flag_special; i++) 177 { 178 flg_spec = &arc_flag_special_cases[i]; 179 180 if (strcmp (opname, flg_spec->name)) 181 continue; 182 183 /* Found potential special case instruction. */ 184 for (j=0;; ++j) 185 { 186 flgidx = flg_spec->flags[j]; 187 if (flgidx == 0) 188 break; /* End of the array. */ 189 190 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0) 191 return TRUE; 192 } 193 } 194 return FALSE; 195} 196 197/* Find opcode from ARC_TABLE given the instruction described by INSN and 198 INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */ 199 200static const struct arc_opcode * 201find_format_from_table (struct disassemble_info *info, 202 const struct arc_opcode *arc_table, 203 unsigned long long insn, 204 unsigned int insn_len, 205 unsigned isa_mask, 206 bfd_boolean *has_limm, 207 bfd_boolean overlaps) 208{ 209 unsigned int i = 0; 210 const struct arc_opcode *opcode = NULL; 211 const struct arc_opcode *t_op = NULL; 212 const unsigned char *opidx; 213 const unsigned char *flgidx; 214 bfd_boolean warn_p = FALSE; 215 216 do 217 { 218 bfd_boolean invalid = FALSE; 219 220 opcode = &arc_table[i++]; 221 222 if (!(opcode->cpu & isa_mask)) 223 continue; 224 225 if (arc_opcode_len (opcode) != (int) insn_len) 226 continue; 227 228 if ((insn & opcode->mask) != opcode->opcode) 229 continue; 230 231 *has_limm = FALSE; 232 233 /* Possible candidate, check the operands. */ 234 for (opidx = opcode->operands; *opidx; opidx++) 235 { 236 int value, limmind; 237 const struct arc_operand *operand = &arc_operands[*opidx]; 238 239 if (operand->flags & ARC_OPERAND_FAKE) 240 continue; 241 242 if (operand->extract) 243 value = (*operand->extract) (insn, &invalid); 244 else 245 value = (insn >> operand->shift) & ((1 << operand->bits) - 1); 246 247 /* Check for LIMM indicator. If it is there, then make sure 248 we pick the right format. */ 249 limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E; 250 if (operand->flags & ARC_OPERAND_IR 251 && !(operand->flags & ARC_OPERAND_LIMM)) 252 { 253 if ((value == 0x3E && insn_len == 4) 254 || (value == limmind && insn_len == 2)) 255 { 256 invalid = TRUE; 257 break; 258 } 259 } 260 261 if (operand->flags & ARC_OPERAND_LIMM 262 && !(operand->flags & ARC_OPERAND_DUPLICATE)) 263 *has_limm = TRUE; 264 } 265 266 /* Check the flags. */ 267 for (flgidx = opcode->flags; *flgidx; flgidx++) 268 { 269 /* Get a valid flag class. */ 270 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx]; 271 const unsigned *flgopridx; 272 int foundA = 0, foundB = 0; 273 unsigned int value; 274 275 /* Check first the extensions. */ 276 if (cl_flags->flag_class & F_CLASS_EXTEND) 277 { 278 value = (insn & 0x1F); 279 if (arcExtMap_condCodeName (value)) 280 continue; 281 } 282 283 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx) 284 { 285 const struct arc_flag_operand *flg_operand = 286 &arc_flag_operands[*flgopridx]; 287 288 value = (insn >> flg_operand->shift) 289 & ((1 << flg_operand->bits) - 1); 290 if (value == flg_operand->code) 291 foundA = 1; 292 if (value) 293 foundB = 1; 294 } 295 296 if (!foundA && foundB) 297 { 298 invalid = TRUE; 299 break; 300 } 301 } 302 303 if (invalid) 304 continue; 305 306 if (insn_len == 4 307 && overlaps) 308 { 309 warn_p = TRUE; 310 t_op = opcode; 311 if (skip_this_opcode (opcode)) 312 continue; 313 } 314 315 /* The instruction is valid. */ 316 return opcode; 317 } 318 while (opcode->mask); 319 320 if (warn_p) 321 { 322 info->fprintf_func (info->stream, 323 _("\nWarning: disassembly may be wrong due to " 324 "guessed opcode class choice.\n" 325 "Use -M<class[,class]> to select the correct " 326 "opcode class(es).\n\t\t\t\t")); 327 return t_op; 328 } 329 330 return NULL; 331} 332 333/* Find opcode for INSN, trying various different sources. The instruction 334 length in INSN_LEN will be updated if the instruction requires a LIMM 335 extension. 336 337 A pointer to the opcode is placed into OPCODE_RESULT, and ITER is 338 initialised, ready to iterate over the operands of the found opcode. If 339 the found opcode requires a LIMM then the LIMM value will be loaded into a 340 field of ITER. 341 342 This function returns TRUE in almost all cases, FALSE is reserved to 343 indicate an error (failing to find an opcode is not an error) a returned 344 result of FALSE would indicate that the disassembler can't continue. 345 346 If no matching opcode is found then the returned result will be TRUE, the 347 value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and 348 INSN_LEN will be unchanged. 349 350 If a matching opcode is found, then the returned result will be TRUE, the 351 opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by 352 4 if the instruction requires a LIMM, and the LIMM value will have been 353 loaded into a field of ITER. Finally, ITER will have been initialised so 354 that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's 355 operands. */ 356 357static bfd_boolean 358find_format (bfd_vma memaddr, 359 unsigned long long insn, 360 unsigned int * insn_len, 361 unsigned isa_mask, 362 struct disassemble_info * info, 363 const struct arc_opcode ** opcode_result, 364 struct arc_operand_iterator * iter) 365{ 366 const struct arc_opcode *opcode = NULL; 367 bfd_boolean needs_limm; 368 const extInstruction_t *einsn, *i; 369 unsigned limm = 0; 370 371 /* First, try the extension instructions. */ 372 if (*insn_len == 4) 373 { 374 einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn); 375 for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next) 376 { 377 const char *errmsg = NULL; 378 379 opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg); 380 if (opcode == NULL) 381 { 382 (*info->fprintf_func) (info->stream, "\ 383An error occured while generating the extension instruction operations"); 384 *opcode_result = NULL; 385 return FALSE; 386 } 387 388 opcode = find_format_from_table (info, opcode, insn, *insn_len, 389 isa_mask, &needs_limm, FALSE); 390 } 391 } 392 393 /* Then, try finding the first match in the opcode table. */ 394 if (opcode == NULL) 395 opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len, 396 isa_mask, &needs_limm, TRUE); 397 398 if (needs_limm && opcode != NULL) 399 { 400 bfd_byte buffer[4]; 401 int status; 402 403 status = (*info->read_memory_func) (memaddr + *insn_len, buffer, 404 4, info); 405 if (status != 0) 406 { 407 opcode = NULL; 408 } 409 else 410 { 411 limm = ARRANGE_ENDIAN (info, buffer); 412 *insn_len += 4; 413 } 414 } 415 416 if (opcode != NULL) 417 { 418 iter->insn = insn; 419 iter->limm = limm; 420 iter->opcode = opcode; 421 iter->opidx = opcode->operands; 422 } 423 424 *opcode_result = opcode; 425 return TRUE; 426} 427 428static void 429print_flags (const struct arc_opcode *opcode, 430 unsigned long long *insn, 431 struct disassemble_info *info) 432{ 433 const unsigned char *flgidx; 434 unsigned int value; 435 436 /* Now extract and print the flags. */ 437 for (flgidx = opcode->flags; *flgidx; flgidx++) 438 { 439 /* Get a valid flag class. */ 440 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx]; 441 const unsigned *flgopridx; 442 443 /* Check first the extensions. */ 444 if (cl_flags->flag_class & F_CLASS_EXTEND) 445 { 446 const char *name; 447 value = (insn[0] & 0x1F); 448 449 name = arcExtMap_condCodeName (value); 450 if (name) 451 { 452 (*info->fprintf_func) (info->stream, ".%s", name); 453 continue; 454 } 455 } 456 457 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx) 458 { 459 const struct arc_flag_operand *flg_operand = 460 &arc_flag_operands[*flgopridx]; 461 462 if (!flg_operand->favail) 463 continue; 464 465 value = (insn[0] >> flg_operand->shift) 466 & ((1 << flg_operand->bits) - 1); 467 if (value == flg_operand->code) 468 { 469 /* FIXME!: print correctly nt/t flag. */ 470 if (!special_flag_p (opcode->name, flg_operand->name)) 471 (*info->fprintf_func) (info->stream, "."); 472 else if (info->insn_type == dis_dref) 473 { 474 switch (flg_operand->name[0]) 475 { 476 case 'b': 477 info->data_size = 1; 478 break; 479 case 'h': 480 case 'w': 481 info->data_size = 2; 482 break; 483 default: 484 info->data_size = 4; 485 break; 486 } 487 } 488 if (flg_operand->name[0] == 'd' 489 && flg_operand->name[1] == 0) 490 info->branch_delay_insns = 1; 491 492 /* Check if it is a conditional flag. */ 493 if (cl_flags->flag_class & F_CLASS_COND) 494 { 495 if (info->insn_type == dis_jsr) 496 info->insn_type = dis_condjsr; 497 else if (info->insn_type == dis_branch) 498 info->insn_type = dis_condbranch; 499 } 500 501 (*info->fprintf_func) (info->stream, "%s", flg_operand->name); 502 } 503 } 504 } 505} 506 507static const char * 508get_auxreg (const struct arc_opcode *opcode, 509 int value, 510 unsigned isa_mask) 511{ 512 const char *name; 513 unsigned int i; 514 const struct arc_aux_reg *auxr = &arc_aux_regs[0]; 515 516 if (opcode->insn_class != AUXREG) 517 return NULL; 518 519 name = arcExtMap_auxRegName (value); 520 if (name) 521 return name; 522 523 for (i = 0; i < arc_num_aux_regs; i++, auxr++) 524 { 525 if (!(auxr->cpu & isa_mask)) 526 continue; 527 528 if (auxr->subclass != NONE) 529 return NULL; 530 531 if (auxr->address == value) 532 return auxr->name; 533 } 534 return NULL; 535} 536 537/* Convert a value representing an address type to a string used to refer to 538 the address type in assembly code. */ 539 540static const char * 541get_addrtype (int value) 542{ 543 if (value < 0 || value > addrtypenames_max) 544 return addrtypeunknown; 545 546 return addrtypenames[value]; 547} 548 549/* Calculate the instruction length for an instruction starting with MSB 550 and LSB, the most and least significant byte. The ISA_MASK is used to 551 filter the instructions considered to only those that are part of the 552 current architecture. 553 554 The instruction lengths are calculated from the ARC_OPCODE table, and 555 cached for later use. */ 556 557static unsigned int 558arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info) 559{ 560 bfd_byte major_opcode = msb >> 3; 561 562 switch (info->mach) 563 { 564 case bfd_mach_arc_arc700: 565 /* The nps400 extension set requires this special casing of the 566 instruction length calculation. Right now this is not causing any 567 problems as none of the known extensions overlap in opcode space, 568 but, if they ever do then we might need to start carrying 569 information around in the elf about which extensions are in use. */ 570 if (major_opcode == 0xb) 571 { 572 bfd_byte minor_opcode = lsb & 0x1f; 573 574 if (minor_opcode < 4) 575 return 6; 576 else if (minor_opcode == 0x10 || minor_opcode == 0x11) 577 return 8; 578 } 579 if (major_opcode == 0xa) 580 { 581 return 8; 582 } 583 /* Fall through. */ 584 case bfd_mach_arc_arc600: 585 return (major_opcode > 0xb) ? 2 : 4; 586 break; 587 588 case bfd_mach_arc_arcv2: 589 return (major_opcode > 0x7) ? 2 : 4; 590 break; 591 592 default: 593 abort (); 594 } 595} 596 597/* Extract and return the value of OPERAND from the instruction whose value 598 is held in the array INSN. */ 599 600static int 601extract_operand_value (const struct arc_operand *operand, 602 unsigned long long insn, 603 unsigned limm) 604{ 605 int value; 606 607 /* Read the limm operand, if required. */ 608 if (operand->flags & ARC_OPERAND_LIMM) 609 /* The second part of the instruction value will have been loaded as 610 part of the find_format call made earlier. */ 611 value = limm; 612 else 613 { 614 if (operand->extract) 615 value = (*operand->extract) (insn, (int *) NULL); 616 else 617 { 618 if (operand->flags & ARC_OPERAND_ALIGNED32) 619 { 620 value = (insn >> operand->shift) 621 & ((1 << (operand->bits - 2)) - 1); 622 value = value << 2; 623 } 624 else 625 { 626 value = (insn >> operand->shift) & ((1 << operand->bits) - 1); 627 } 628 if (operand->flags & ARC_OPERAND_SIGNED) 629 { 630 int signbit = 1 << (operand->bits - 1); 631 value = (value ^ signbit) - signbit; 632 } 633 } 634 } 635 636 return value; 637} 638 639/* Find the next operand, and the operands value from ITER. Return TRUE if 640 there is another operand, otherwise return FALSE. If there is an 641 operand returned then the operand is placed into OPERAND, and the value 642 into VALUE. If there is no operand returned then OPERAND and VALUE are 643 unchanged. */ 644 645static bfd_boolean 646operand_iterator_next (struct arc_operand_iterator *iter, 647 const struct arc_operand **operand, 648 int *value) 649{ 650 if (*iter->opidx == 0) 651 { 652 *operand = NULL; 653 return FALSE; 654 } 655 656 *operand = &arc_operands[*iter->opidx]; 657 *value = extract_operand_value (*operand, iter->insn, iter->limm); 658 iter->opidx++; 659 660 return TRUE; 661} 662 663/* Helper for parsing the options. */ 664 665static void 666parse_option (char *option) 667{ 668 if (CONST_STRNEQ (option, "dsp")) 669 add_to_decodelist (DSP, NONE); 670 671 else if (CONST_STRNEQ (option, "spfp")) 672 add_to_decodelist (FLOAT, SPX); 673 674 else if (CONST_STRNEQ (option, "dpfp")) 675 add_to_decodelist (FLOAT, DPX); 676 677 else if (CONST_STRNEQ (option, "quarkse_em")) 678 { 679 add_to_decodelist (FLOAT, DPX); 680 add_to_decodelist (FLOAT, SPX); 681 add_to_decodelist (FLOAT, QUARKSE); 682 } 683 684 else if (CONST_STRNEQ (option, "fpuda")) 685 add_to_decodelist (FLOAT, DPA); 686 687 else if (CONST_STRNEQ (option, "fpus")) 688 { 689 add_to_decodelist (FLOAT, SP); 690 add_to_decodelist (FLOAT, CVT); 691 } 692 693 else if (CONST_STRNEQ (option, "fpud")) 694 { 695 add_to_decodelist (FLOAT, DP); 696 add_to_decodelist (FLOAT, CVT); 697 } 698 else 699 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option); 700} 701 702/* Go over the options list and parse it. */ 703 704static void 705parse_disassembler_options (char *options) 706{ 707 if (options == NULL) 708 return; 709 710 while (*options) 711 { 712 /* Skip empty options. */ 713 if (*options == ',') 714 { 715 ++ options; 716 continue; 717 } 718 719 parse_option (options); 720 721 while (*options != ',' && *options != '\0') 722 ++ options; 723 } 724} 725 726/* Return the instruction type for an instruction described by OPCODE. */ 727 728static enum dis_insn_type 729arc_opcode_to_insn_type (const struct arc_opcode *opcode) 730{ 731 enum dis_insn_type insn_type; 732 733 switch (opcode->insn_class) 734 { 735 case BRANCH: 736 case JUMP: 737 if (!strncmp (opcode->name, "bl", 2) 738 || !strncmp (opcode->name, "jl", 2)) 739 { 740 if (opcode->subclass == COND) 741 insn_type = dis_condjsr; 742 else 743 insn_type = dis_jsr; 744 } 745 else 746 { 747 if (opcode->subclass == COND) 748 insn_type = dis_condbranch; 749 else 750 insn_type = dis_branch; 751 } 752 break; 753 case LOAD: 754 case STORE: 755 case MEMORY: 756 insn_type = dis_dref; 757 break; 758 default: 759 insn_type = dis_nonbranch; 760 break; 761 } 762 763 return insn_type; 764} 765 766/* Disassemble ARC instructions. */ 767 768static int 769print_insn_arc (bfd_vma memaddr, 770 struct disassemble_info *info) 771{ 772 bfd_byte buffer[8]; 773 unsigned int highbyte, lowbyte; 774 int status; 775 unsigned int insn_len; 776 unsigned long long insn = 0; 777 unsigned isa_mask; 778 const struct arc_opcode *opcode; 779 bfd_boolean need_comma; 780 bfd_boolean open_braket; 781 int size; 782 const struct arc_operand *operand; 783 int value; 784 struct arc_operand_iterator iter; 785 Elf_Internal_Ehdr *header = NULL; 786 787 if (info->disassembler_options) 788 { 789 parse_disassembler_options (info->disassembler_options); 790 791 /* Avoid repeated parsing of the options. */ 792 info->disassembler_options = NULL; 793 } 794 795 memset (&iter, 0, sizeof (iter)); 796 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0); 797 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1); 798 799 if (info->section && info->section->owner) 800 header = elf_elfheader (info->section->owner); 801 802 switch (info->mach) 803 { 804 case bfd_mach_arc_arc700: 805 isa_mask = ARC_OPCODE_ARC700; 806 break; 807 808 case bfd_mach_arc_arc600: 809 isa_mask = ARC_OPCODE_ARC600; 810 break; 811 812 case bfd_mach_arc_arcv2: 813 default: 814 isa_mask = ARC_OPCODE_ARCv2EM; 815 /* TODO: Perhaps remove defitinion of header since it is only used at 816 this location. */ 817 if (header != NULL 818 && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS) 819 { 820 isa_mask = ARC_OPCODE_ARCv2HS; 821 /* FPU instructions are not extensions for HS. */ 822 add_to_decodelist (FLOAT, SP); 823 add_to_decodelist (FLOAT, DP); 824 add_to_decodelist (FLOAT, CVT); 825 } 826 break; 827 } 828 829 /* This variable may be set by the instruction decoder. It suggests 830 the number of bytes objdump should display on a single line. If 831 the instruction decoder sets this, it should always set it to 832 the same value in order to get reasonable looking output. */ 833 834 info->bytes_per_line = 8; 835 836 /* In the next lines, we set two info variables control the way 837 objdump displays the raw data. For example, if bytes_per_line is 838 8 and bytes_per_chunk is 4, the output will look like this: 839 00: 00000000 00000000 840 with the chunks displayed according to "display_endian". */ 841 842 if (info->section 843 && !(info->section->flags & SEC_CODE)) 844 { 845 /* This is not a CODE section. */ 846 switch (info->section->size) 847 { 848 case 1: 849 case 2: 850 case 4: 851 size = info->section->size; 852 break; 853 default: 854 size = (info->section->size & 0x01) ? 1 : 4; 855 break; 856 } 857 info->bytes_per_chunk = 1; 858 info->display_endian = info->endian; 859 } 860 else 861 { 862 size = 2; 863 info->bytes_per_chunk = 2; 864 info->display_endian = info->endian; 865 } 866 867 /* Read the insn into a host word. */ 868 status = (*info->read_memory_func) (memaddr, buffer, size, info); 869 if (status != 0) 870 { 871 (*info->memory_error_func) (status, memaddr, info); 872 return -1; 873 } 874 875 if (info->section 876 && !(info->section->flags & SEC_CODE)) 877 { 878 /* Data section. */ 879 unsigned long data; 880 881 data = bfd_get_bits (buffer, size * 8, 882 info->display_endian == BFD_ENDIAN_BIG); 883 switch (size) 884 { 885 case 1: 886 (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data); 887 break; 888 case 2: 889 (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data); 890 break; 891 case 4: 892 (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data); 893 break; 894 default: 895 abort (); 896 } 897 return size; 898 } 899 900 insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info); 901 pr_debug ("instruction length = %d bytes\n", insn_len); 902 903 switch (insn_len) 904 { 905 case 2: 906 insn = (buffer[highbyte] << 8) | buffer[lowbyte]; 907 break; 908 909 case 4: 910 { 911 /* This is a long instruction: Read the remaning 2 bytes. */ 912 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info); 913 if (status != 0) 914 { 915 (*info->memory_error_func) (status, memaddr + 2, info); 916 return -1; 917 } 918 insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer); 919 } 920 break; 921 922 case 6: 923 { 924 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info); 925 if (status != 0) 926 { 927 (*info->memory_error_func) (status, memaddr + 2, info); 928 return -1; 929 } 930 insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]); 931 insn |= ((unsigned long long) buffer[highbyte] << 40) 932 | ((unsigned long long) buffer[lowbyte] << 32); 933 } 934 break; 935 936 case 8: 937 { 938 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info); 939 if (status != 0) 940 { 941 (*info->memory_error_func) (status, memaddr + 2, info); 942 return -1; 943 } 944 insn = 945 ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32) 946 | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4]))); 947 } 948 break; 949 950 default: 951 /* There is no instruction whose length is not 2, 4, 6, or 8. */ 952 abort (); 953 } 954 955 pr_debug ("instruction value = %llx\n", insn); 956 957 /* Set some defaults for the insn info. */ 958 info->insn_info_valid = 1; 959 info->branch_delay_insns = 0; 960 info->data_size = 0; 961 info->insn_type = dis_nonbranch; 962 info->target = 0; 963 info->target2 = 0; 964 965 /* FIXME to be moved in dissasemble_init_for_target. */ 966 info->disassembler_needs_relocs = TRUE; 967 968 /* Find the first match in the opcode table. */ 969 if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter)) 970 return -1; 971 972 if (!opcode) 973 { 974 switch (insn_len) 975 { 976 case 2: 977 (*info->fprintf_func) (info->stream, ".long %#04llx", 978 insn & 0xffff); 979 break; 980 case 4: 981 (*info->fprintf_func) (info->stream, ".long %#08llx", 982 insn & 0xffffffff); 983 break; 984 case 6: 985 (*info->fprintf_func) (info->stream, ".long %#08llx", 986 insn & 0xffffffff); 987 (*info->fprintf_func) (info->stream, ".long %#04llx", 988 (insn >> 32) & 0xffff); 989 break; 990 case 8: 991 (*info->fprintf_func) (info->stream, ".long %#08llx", 992 insn & 0xffffffff); 993 (*info->fprintf_func) (info->stream, ".long %#08llx", 994 insn >> 32); 995 break; 996 default: 997 abort (); 998 } 999 1000 info->insn_type = dis_noninsn; 1001 return insn_len; 1002 } 1003 1004 /* Print the mnemonic. */ 1005 (*info->fprintf_func) (info->stream, "%s", opcode->name); 1006 1007 /* Preselect the insn class. */ 1008 info->insn_type = arc_opcode_to_insn_type (opcode); 1009 1010 pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode); 1011 1012 print_flags (opcode, &insn, info); 1013 1014 if (opcode->operands[0] != 0) 1015 (*info->fprintf_func) (info->stream, "\t"); 1016 1017 need_comma = FALSE; 1018 open_braket = FALSE; 1019 1020 /* Now extract and print the operands. */ 1021 operand = NULL; 1022 while (operand_iterator_next (&iter, &operand, &value)) 1023 { 1024 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET)) 1025 { 1026 (*info->fprintf_func) (info->stream, "]"); 1027 open_braket = FALSE; 1028 continue; 1029 } 1030 1031 /* Only take input from real operands. */ 1032 if (ARC_OPERAND_IS_FAKE (operand)) 1033 continue; 1034 1035 if ((operand->flags & ARC_OPERAND_IGNORE) 1036 && (operand->flags & ARC_OPERAND_IR) 1037 && value == -1) 1038 continue; 1039 1040 if (operand->flags & ARC_OPERAND_COLON) 1041 { 1042 (*info->fprintf_func) (info->stream, ":"); 1043 continue; 1044 } 1045 1046 if (need_comma) 1047 (*info->fprintf_func) (info->stream, ","); 1048 1049 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET)) 1050 { 1051 (*info->fprintf_func) (info->stream, "["); 1052 open_braket = TRUE; 1053 need_comma = FALSE; 1054 continue; 1055 } 1056 1057 need_comma = TRUE; 1058 1059 /* Print the operand as directed by the flags. */ 1060 if (operand->flags & ARC_OPERAND_IR) 1061 { 1062 const char *rname; 1063 1064 assert (value >=0 && value < 64); 1065 rname = arcExtMap_coreRegName (value); 1066 if (!rname) 1067 rname = regnames[value]; 1068 (*info->fprintf_func) (info->stream, "%s", rname); 1069 if (operand->flags & ARC_OPERAND_TRUNCATE) 1070 { 1071 rname = arcExtMap_coreRegName (value + 1); 1072 if (!rname) 1073 rname = regnames[value + 1]; 1074 (*info->fprintf_func) (info->stream, "%s", rname); 1075 } 1076 } 1077 else if (operand->flags & ARC_OPERAND_LIMM) 1078 { 1079 const char *rname = get_auxreg (opcode, value, isa_mask); 1080 1081 if (rname && open_braket) 1082 (*info->fprintf_func) (info->stream, "%s", rname); 1083 else 1084 { 1085 (*info->fprintf_func) (info->stream, "%#x", value); 1086 if (info->insn_type == dis_branch 1087 || info->insn_type == dis_jsr) 1088 info->target = (bfd_vma) value; 1089 } 1090 } 1091 else if (operand->flags & ARC_OPERAND_PCREL) 1092 { 1093 /* PCL relative. */ 1094 if (info->flags & INSN_HAS_RELOC) 1095 memaddr = 0; 1096 (*info->print_address_func) ((memaddr & ~3) + value, info); 1097 1098 info->target = (bfd_vma) (memaddr & ~3) + value; 1099 } 1100 else if (operand->flags & ARC_OPERAND_SIGNED) 1101 { 1102 const char *rname = get_auxreg (opcode, value, isa_mask); 1103 if (rname && open_braket) 1104 (*info->fprintf_func) (info->stream, "%s", rname); 1105 else 1106 (*info->fprintf_func) (info->stream, "%d", value); 1107 } 1108 else if (operand->flags & ARC_OPERAND_ADDRTYPE) 1109 { 1110 const char *addrtype = get_addrtype (value); 1111 (*info->fprintf_func) (info->stream, "%s", addrtype); 1112 /* A colon follow an address type. */ 1113 need_comma = FALSE; 1114 } 1115 else 1116 { 1117 if (operand->flags & ARC_OPERAND_TRUNCATE 1118 && !(operand->flags & ARC_OPERAND_ALIGNED32) 1119 && !(operand->flags & ARC_OPERAND_ALIGNED16) 1120 && value > 0 && value <= 14) 1121 (*info->fprintf_func) (info->stream, "r13-%s", 1122 regnames[13 + value - 1]); 1123 else 1124 { 1125 const char *rname = get_auxreg (opcode, value, isa_mask); 1126 if (rname && open_braket) 1127 (*info->fprintf_func) (info->stream, "%s", rname); 1128 else 1129 (*info->fprintf_func) (info->stream, "%#x", value); 1130 } 1131 } 1132 } 1133 1134 return insn_len; 1135} 1136 1137 1138disassembler_ftype 1139arc_get_disassembler (bfd *abfd) 1140{ 1141 /* BFD my be absent, if opcodes is invoked from the debugger that 1142 has connected to remote target and doesn't have an ELF file. */ 1143 if (abfd != NULL) 1144 { 1145 /* Read the extension insns and registers, if any. */ 1146 build_ARC_extmap (abfd); 1147#ifdef DEBUG 1148 dump_ARC_extmap (); 1149#endif 1150 } 1151 1152 return print_insn_arc; 1153} 1154 1155/* Disassemble ARC instructions. Used by debugger. */ 1156 1157struct arcDisState 1158arcAnalyzeInstr (bfd_vma memaddr, 1159 struct disassemble_info *info) 1160{ 1161 struct arcDisState ret; 1162 memset (&ret, 0, sizeof (struct arcDisState)); 1163 1164 ret.instructionLen = print_insn_arc (memaddr, info); 1165 1166#if 0 1167 ret.words[0] = insn[0]; 1168 ret.words[1] = insn[1]; 1169 ret._this = &ret; 1170 ret.coreRegName = _coreRegName; 1171 ret.auxRegName = _auxRegName; 1172 ret.condCodeName = _condCodeName; 1173 ret.instName = _instName; 1174#endif 1175 1176 return ret; 1177} 1178 1179void 1180print_arc_disassembler_options (FILE *stream) 1181{ 1182 fprintf (stream, _("\n\ 1183The following ARC specific disassembler options are supported for use \n\ 1184with -M switch (multiple options should be separated by commas):\n")); 1185 1186 fprintf (stream, _("\ 1187 dsp Recognize DSP instructions.\n")); 1188 fprintf (stream, _("\ 1189 spfp Recognize FPX SP instructions.\n")); 1190 fprintf (stream, _("\ 1191 dpfp Recognize FPX DP instructions.\n")); 1192 fprintf (stream, _("\ 1193 quarkse_em Recognize FPU QuarkSE-EM instructions.\n")); 1194 fprintf (stream, _("\ 1195 fpuda Recognize double assist FPU instructions.\n")); 1196 fprintf (stream, _("\ 1197 fpus Recognize single precision FPU instructions.\n")); 1198 fprintf (stream, _("\ 1199 fpud Recognize double precision FPU instructions.\n")); 1200} 1201 1202 1203/* Local variables: 1204 eval: (c-set-style "gnu") 1205 indent-tabs-mode: t 1206 End: */ 1207