1 /* Instruction printing code for the ARC. 2 Copyright (C) 1994-2016 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 "arc-dis.h" 29 #include "arc-ext.h" 30 31 /* Structure used to iterate over, and extract the values for, operands of 32 an opcode. */ 33 34 struct arc_operand_iterator 35 { 36 enum 37 { 38 OPERAND_ITERATOR_STANDARD, 39 OPERAND_ITERATOR_LONG 40 } mode; 41 42 /* The array of 32-bit values that make up this instruction. All 43 required values have been pre-loaded into this array during the 44 find_format call. */ 45 unsigned *insn; 46 47 union 48 { 49 struct 50 { 51 /* The opcode this iterator is operating on. */ 52 const struct arc_opcode *opcode; 53 54 /* The index into the opcodes operand index list. */ 55 const unsigned char *opidx; 56 } standard; 57 58 struct 59 { 60 /* The long instruction opcode this iterator is operating on. */ 61 const struct arc_long_opcode *long_opcode; 62 63 /* Two indexes into the opcodes operand index lists. */ 64 const unsigned char *opidx_base, *opidx_limm; 65 } long_insn; 66 } state; 67 }; 68 69 /* Globals variables. */ 70 71 static const char * const regnames[64] = 72 { 73 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 74 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 75 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 76 "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink", 77 78 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", 79 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", 80 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", 81 "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl" 82 }; 83 84 /* Macros section. */ 85 86 #ifdef DEBUG 87 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args) 88 #else 89 # define pr_debug(fmt, args...) 90 #endif 91 92 #define ARRANGE_ENDIAN(info, buf) \ 93 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \ 94 : bfd_getb32 (buf)) 95 96 #define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \ 97 (s + (sizeof (word) * 8 - 1 - e))) 98 #define OPCODE(word) (BITS ((word), 27, 31)) 99 100 #define OPCODE_AC(word) (BITS ((word), 11, 15)) 101 102 /* Functions implementation. */ 103 104 static bfd_vma 105 bfd_getm32 (unsigned int data) 106 { 107 bfd_vma value = 0; 108 109 value = ((data & 0xff00) | (data & 0xff)) << 16; 110 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16; 111 return value; 112 } 113 114 static int 115 special_flag_p (const char *opname, 116 const char *flgname) 117 { 118 const struct arc_flag_special *flg_spec; 119 unsigned i, j, flgidx; 120 121 for (i = 0; i < arc_num_flag_special; i++) 122 { 123 flg_spec = &arc_flag_special_cases[i]; 124 125 if (strcmp (opname, flg_spec->name)) 126 continue; 127 128 /* Found potential special case instruction. */ 129 for (j=0;; ++j) 130 { 131 flgidx = flg_spec->flags[j]; 132 if (flgidx == 0) 133 break; /* End of the array. */ 134 135 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0) 136 return 1; 137 } 138 } 139 return 0; 140 } 141 142 /* Find opcode from ARC_TABLE given the instruction described by INSN and 143 INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */ 144 145 static const struct arc_opcode * 146 find_format_from_table (const struct arc_opcode *arc_table, 147 unsigned *insn, unsigned int insn_len, 148 unsigned isa_mask, bfd_boolean *has_limm) 149 { 150 unsigned int i = 0; 151 const struct arc_opcode *opcode = NULL; 152 const unsigned char *opidx; 153 const unsigned char *flgidx; 154 155 do { 156 bfd_boolean invalid = FALSE; 157 158 opcode = &arc_table[i++]; 159 160 if (ARC_SHORT (opcode->mask) && (insn_len == 2)) 161 { 162 if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0])) 163 continue; 164 } 165 else if (!ARC_SHORT (opcode->mask) && (insn_len == 4)) 166 { 167 if (OPCODE (opcode->opcode) != OPCODE (insn[0])) 168 continue; 169 } 170 else 171 continue; 172 173 if ((insn[0] ^ opcode->opcode) & opcode->mask) 174 continue; 175 176 if (!(opcode->cpu & isa_mask)) 177 continue; 178 179 *has_limm = FALSE; 180 181 /* Possible candidate, check the operands. */ 182 for (opidx = opcode->operands; *opidx; opidx++) 183 { 184 int value; 185 const struct arc_operand *operand = &arc_operands[*opidx]; 186 187 if (operand->flags & ARC_OPERAND_FAKE) 188 continue; 189 190 if (operand->extract) 191 value = (*operand->extract) (insn[0], &invalid); 192 else 193 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1); 194 195 /* Check for LIMM indicator. If it is there, then make sure 196 we pick the right format. */ 197 if (operand->flags & ARC_OPERAND_IR 198 && !(operand->flags & ARC_OPERAND_LIMM)) 199 { 200 if ((value == 0x3E && insn_len == 4) 201 || (value == 0x1E && insn_len == 2)) 202 { 203 invalid = TRUE; 204 break; 205 } 206 } 207 208 if (operand->flags & ARC_OPERAND_LIMM 209 && !(operand->flags & ARC_OPERAND_DUPLICATE)) 210 *has_limm = TRUE; 211 } 212 213 /* Check the flags. */ 214 for (flgidx = opcode->flags; *flgidx; flgidx++) 215 { 216 /* Get a valid flag class. */ 217 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx]; 218 const unsigned *flgopridx; 219 int foundA = 0, foundB = 0; 220 unsigned int value; 221 222 /* Check first the extensions. */ 223 if (cl_flags->flag_class & F_CLASS_EXTEND) 224 { 225 value = (insn[0] & 0x1F); 226 if (arcExtMap_condCodeName (value)) 227 continue; 228 } 229 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx) 230 { 231 const struct arc_flag_operand *flg_operand = 232 &arc_flag_operands[*flgopridx]; 233 234 value = (insn[0] >> flg_operand->shift) 235 & ((1 << flg_operand->bits) - 1); 236 if (value == flg_operand->code) 237 foundA = 1; 238 if (value) 239 foundB = 1; 240 } 241 if (!foundA && foundB) 242 { 243 invalid = TRUE; 244 break; 245 } 246 } 247 248 if (invalid) 249 continue; 250 251 /* The instruction is valid. */ 252 return opcode; 253 } while (opcode->mask); 254 255 return NULL; 256 } 257 258 /* Find long instructions matching values in INSN array. */ 259 260 static const struct arc_long_opcode * 261 find_format_long_instructions (unsigned *insn, 262 unsigned int *insn_len, 263 unsigned isa_mask, 264 bfd_vma memaddr, 265 struct disassemble_info *info) 266 { 267 unsigned int i; 268 unsigned limm = 0; 269 bfd_boolean limm_loaded = FALSE; 270 271 for (i = 0; i < arc_num_long_opcodes; ++i) 272 { 273 bfd_byte buffer[4]; 274 int status; 275 const struct arc_opcode *opcode; 276 277 opcode = &arc_long_opcodes[i].base_opcode; 278 279 if (ARC_SHORT (opcode->mask) && (*insn_len == 2)) 280 { 281 if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0])) 282 continue; 283 } 284 else if (!ARC_SHORT (opcode->mask) && (*insn_len == 4)) 285 { 286 if (OPCODE (opcode->opcode) != OPCODE (insn[0])) 287 continue; 288 } 289 else 290 continue; 291 292 if ((insn[0] ^ opcode->opcode) & opcode->mask) 293 continue; 294 295 if (!(opcode->cpu & isa_mask)) 296 continue; 297 298 if (!limm_loaded) 299 { 300 status = (*info->read_memory_func) (memaddr + *insn_len, buffer, 301 4, info); 302 if (status != 0) 303 return NULL; 304 305 limm = ARRANGE_ENDIAN (info, buffer); 306 limm_loaded = TRUE; 307 } 308 309 /* Check the second word using the mask and template. */ 310 if ((limm & arc_long_opcodes[i].limm_mask) 311 != arc_long_opcodes[i].limm_template) 312 continue; 313 314 (*insn_len) += 4; 315 insn[1] = limm; 316 return &arc_long_opcodes[i]; 317 } 318 319 return NULL; 320 } 321 322 /* Find opcode for INSN, trying various different sources. The instruction 323 length in INSN_LEN will be updated if the instruction requires a LIMM 324 extension, and the additional values loaded into the INSN array (which 325 must be big enough). 326 327 A pointer to the opcode is placed into OPCODE_RESULT, and ITER is 328 initialised, ready to iterate over the operands of the found opcode. 329 330 This function returns TRUE in almost all cases, FALSE is reserved to 331 indicate an error (failing to find an opcode is not an error) a 332 returned result of FALSE would indicate that the disassembler can't 333 continue. 334 335 If no matching opcode is found then the returned result will be TRUE, 336 the value placed into OPCODE_RESULT will be NULL, ITER will be 337 undefined, and INSN_LEN will be unchanged. 338 339 If a matching opcode is found, then the returned result will be TRUE, 340 the opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be 341 increased by 4 if the instruction requires a LIMM, and the LIMM value 342 will have been loaded into the INSN[1]. Finally, ITER will have been 343 initialised so that calls to OPERAND_ITERATOR_NEXT will iterate over 344 the opcode's operands. */ 345 346 static bfd_boolean 347 find_format (bfd_vma memaddr, unsigned *insn, unsigned int *insn_len, 348 unsigned isa_mask, struct disassemble_info *info, 349 const struct arc_opcode **opcode_result, 350 struct arc_operand_iterator *iter) 351 { 352 const struct arc_opcode *opcode; 353 bfd_boolean needs_limm; 354 355 /* Find the first match in the opcode table. */ 356 opcode = find_format_from_table (arc_opcodes, insn, *insn_len, 357 isa_mask, &needs_limm); 358 359 if (opcode == NULL) 360 { 361 const extInstruction_t *einsn; 362 363 /* No instruction found. Try the extensions. */ 364 einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]); 365 if (einsn != NULL) 366 { 367 const char *errmsg = NULL; 368 opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg); 369 if (opcode == NULL) 370 { 371 (*info->fprintf_func) (info->stream, 372 "An error occured while " 373 "generating the extension instruction " 374 "operations"); 375 *opcode_result = NULL; 376 return FALSE; 377 } 378 379 opcode = find_format_from_table (opcode, insn, *insn_len, 380 isa_mask, &needs_limm); 381 assert (opcode != NULL); 382 } 383 } 384 385 if (needs_limm && opcode != NULL) 386 { 387 bfd_byte buffer[4]; 388 int status; 389 390 status = (*info->read_memory_func) (memaddr + *insn_len, buffer, 391 4, info); 392 if (status != 0) 393 { 394 opcode = NULL; 395 } 396 else 397 { 398 insn[1] = ARRANGE_ENDIAN (info, buffer); 399 *insn_len += 4; 400 } 401 } 402 403 if (opcode == NULL) 404 { 405 const struct arc_long_opcode *long_opcode; 406 407 /* No instruction found yet, try the long instructions. */ 408 long_opcode = 409 find_format_long_instructions (insn, insn_len, isa_mask, 410 memaddr, info); 411 412 if (long_opcode != NULL) 413 { 414 iter->mode = OPERAND_ITERATOR_LONG; 415 iter->insn = insn; 416 iter->state.long_insn.long_opcode = long_opcode; 417 iter->state.long_insn.opidx_base = 418 long_opcode->base_opcode.operands; 419 iter->state.long_insn.opidx_limm = 420 long_opcode->operands; 421 opcode = &long_opcode->base_opcode; 422 } 423 } 424 else 425 { 426 iter->mode = OPERAND_ITERATOR_STANDARD; 427 iter->insn = insn; 428 iter->state.standard.opcode = opcode; 429 iter->state.standard.opidx = opcode->operands; 430 } 431 432 *opcode_result = opcode; 433 return TRUE; 434 } 435 436 static void 437 print_flags (const struct arc_opcode *opcode, 438 unsigned *insn, 439 struct disassemble_info *info) 440 { 441 const unsigned char *flgidx; 442 unsigned int value; 443 444 /* Now extract and print the flags. */ 445 for (flgidx = opcode->flags; *flgidx; flgidx++) 446 { 447 /* Get a valid flag class. */ 448 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx]; 449 const unsigned *flgopridx; 450 451 /* Check first the extensions. */ 452 if (cl_flags->flag_class & F_CLASS_EXTEND) 453 { 454 const char *name; 455 value = (insn[0] & 0x1F); 456 457 name = arcExtMap_condCodeName (value); 458 if (name) 459 { 460 (*info->fprintf_func) (info->stream, ".%s", name); 461 continue; 462 } 463 } 464 465 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx) 466 { 467 const struct arc_flag_operand *flg_operand = 468 &arc_flag_operands[*flgopridx]; 469 470 if (!flg_operand->favail) 471 continue; 472 473 value = (insn[0] >> flg_operand->shift) 474 & ((1 << flg_operand->bits) - 1); 475 if (value == flg_operand->code) 476 { 477 /* FIXME!: print correctly nt/t flag. */ 478 if (!special_flag_p (opcode->name, flg_operand->name)) 479 (*info->fprintf_func) (info->stream, "."); 480 else if (info->insn_type == dis_dref) 481 { 482 switch (flg_operand->name[0]) 483 { 484 case 'b': 485 info->data_size = 1; 486 break; 487 case 'h': 488 case 'w': 489 info->data_size = 2; 490 break; 491 default: 492 info->data_size = 4; 493 break; 494 } 495 } 496 if (flg_operand->name[0] == 'd' 497 && flg_operand->name[1] == 0) 498 info->branch_delay_insns = 1; 499 500 /* Check if it is a conditional flag. */ 501 if (cl_flags->flag_class & F_CLASS_COND) 502 { 503 if (info->insn_type == dis_jsr) 504 info->insn_type = dis_condjsr; 505 else if (info->insn_type == dis_branch) 506 info->insn_type = dis_condbranch; 507 } 508 509 (*info->fprintf_func) (info->stream, "%s", flg_operand->name); 510 } 511 } 512 } 513 } 514 515 static const char * 516 get_auxreg (const struct arc_opcode *opcode, 517 int value, 518 unsigned isa_mask) 519 { 520 const char *name; 521 unsigned int i; 522 const struct arc_aux_reg *auxr = &arc_aux_regs[0]; 523 524 if (opcode->insn_class != AUXREG) 525 return NULL; 526 527 name = arcExtMap_auxRegName (value); 528 if (name) 529 return name; 530 531 for (i = 0; i < arc_num_aux_regs; i++, auxr++) 532 { 533 if (!(auxr->cpu & isa_mask)) 534 continue; 535 536 if (auxr->subclass != NONE) 537 return NULL; 538 539 if (auxr->address == value) 540 return auxr->name; 541 } 542 return NULL; 543 } 544 545 /* Calculate the instruction length for an instruction starting with MSB 546 and LSB, the most and least significant byte. The ISA_MASK is used to 547 filter the instructions considered to only those that are part of the 548 current architecture. 549 550 The instruction lengths are calculated from the ARC_OPCODE table, and 551 cached for later use. */ 552 553 static unsigned int 554 arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info) 555 { 556 bfd_byte major_opcode = msb >> 3; 557 558 switch (info->mach) 559 { 560 case bfd_mach_arc_arc700: 561 /* The nps400 extension set requires this special casing of the 562 instruction length calculation. Right now this is not causing any 563 problems as none of the known extensions overlap in opcode space, 564 but, if they ever do then we might need to start carrying 565 information around in the elf about which extensions are in use. */ 566 if (major_opcode == 0xb) 567 { 568 bfd_byte minor_opcode = lsb & 0x1f; 569 570 if (minor_opcode < 4) 571 return 2; 572 } 573 case bfd_mach_arc_arc600: 574 return (major_opcode > 0xb) ? 2 : 4; 575 break; 576 577 case bfd_mach_arc_arcv2: 578 return (major_opcode > 0x7) ? 2 : 4; 579 break; 580 581 default: 582 abort (); 583 } 584 } 585 586 /* Extract and return the value of OPERAND from the instruction whose value 587 is held in the array INSN. */ 588 589 static int 590 extract_operand_value (const struct arc_operand *operand, unsigned *insn) 591 { 592 int value; 593 594 /* Read the limm operand, if required. */ 595 if (operand->flags & ARC_OPERAND_LIMM) 596 /* The second part of the instruction value will have been loaded as 597 part of the find_format call made earlier. */ 598 value = insn[1]; 599 else 600 { 601 if (operand->extract) 602 value = (*operand->extract) (insn[0], (int *) NULL); 603 else 604 { 605 if (operand->flags & ARC_OPERAND_ALIGNED32) 606 { 607 value = (insn[0] >> operand->shift) 608 & ((1 << (operand->bits - 2)) - 1); 609 value = value << 2; 610 } 611 else 612 { 613 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1); 614 } 615 if (operand->flags & ARC_OPERAND_SIGNED) 616 { 617 int signbit = 1 << (operand->bits - 1); 618 value = (value ^ signbit) - signbit; 619 } 620 } 621 } 622 623 return value; 624 } 625 626 /* Find the next operand, and the operands value from ITER. Return TRUE if 627 there is another operand, otherwise return FALSE. If there is an 628 operand returned then the operand is placed into OPERAND, and the value 629 into VALUE. If there is no operand returned then OPERAND and VALUE are 630 unchanged. */ 631 632 static bfd_boolean 633 operand_iterator_next (struct arc_operand_iterator *iter, 634 const struct arc_operand **operand, 635 int *value) 636 { 637 if (iter->mode == OPERAND_ITERATOR_STANDARD) 638 { 639 if (*iter->state.standard.opidx == 0) 640 { 641 *operand = NULL; 642 return FALSE; 643 } 644 645 *operand = &arc_operands[*iter->state.standard.opidx]; 646 *value = extract_operand_value (*operand, iter->insn); 647 iter->state.standard.opidx++; 648 } 649 else 650 { 651 const struct arc_operand *operand_base, *operand_limm; 652 int value_base, value_limm; 653 654 if (*iter->state.long_insn.opidx_limm == 0) 655 { 656 *operand = NULL; 657 return FALSE; 658 } 659 660 operand_base = &arc_operands[*iter->state.long_insn.opidx_base]; 661 operand_limm = &arc_operands[*iter->state.long_insn.opidx_limm]; 662 663 if (operand_base->flags & ARC_OPERAND_LIMM) 664 { 665 /* We've reached the end of the operand list. */ 666 *operand = NULL; 667 return FALSE; 668 } 669 670 value_base = value_limm = 0; 671 if (!(operand_limm->flags & ARC_OPERAND_IGNORE)) 672 { 673 /* This should never happen. If it does then the use of 674 extract_operand_value below will access memory beyond 675 the insn array. */ 676 assert ((operand_limm->flags & ARC_OPERAND_LIMM) == 0); 677 678 *operand = operand_limm; 679 value_limm = extract_operand_value (*operand, &iter->insn[1]); 680 } 681 682 if (!(operand_base->flags & ARC_OPERAND_IGNORE)) 683 { 684 *operand = operand_base; 685 value_base = extract_operand_value (*operand, iter->insn); 686 } 687 688 /* This is a bit of a fudge. There's no reason why simply ORing 689 together the two values is the right thing to do, however, for all 690 the cases we currently have, it is the right thing, so, for now, 691 I've put off solving the more complex problem. */ 692 *value = value_base | value_limm; 693 694 iter->state.long_insn.opidx_base++; 695 iter->state.long_insn.opidx_limm++; 696 } 697 return TRUE; 698 } 699 700 /* Disassemble ARC instructions. */ 701 702 static int 703 print_insn_arc (bfd_vma memaddr, 704 struct disassemble_info *info) 705 { 706 bfd_byte buffer[4]; 707 unsigned int lowbyte, highbyte; 708 int status; 709 unsigned int insn_len; 710 unsigned insn[2] = { 0, 0 }; 711 unsigned isa_mask; 712 const struct arc_opcode *opcode; 713 bfd_boolean need_comma; 714 bfd_boolean open_braket; 715 int size; 716 const struct arc_operand *operand; 717 int value; 718 struct arc_operand_iterator iter; 719 720 memset (&iter, 0, sizeof (iter)); 721 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0); 722 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1); 723 724 switch (info->mach) 725 { 726 case bfd_mach_arc_arc700: 727 isa_mask = ARC_OPCODE_ARC700; 728 break; 729 730 case bfd_mach_arc_arc600: 731 isa_mask = ARC_OPCODE_ARC600; 732 break; 733 734 case bfd_mach_arc_arcv2: 735 default: 736 isa_mask = ARC_OPCODE_ARCv2HS | ARC_OPCODE_ARCv2EM; 737 break; 738 } 739 740 /* This variable may be set by the instruction decoder. It suggests 741 the number of bytes objdump should display on a single line. If 742 the instruction decoder sets this, it should always set it to 743 the same value in order to get reasonable looking output. */ 744 745 info->bytes_per_line = 8; 746 747 /* In the next lines, we set two info variables control the way 748 objdump displays the raw data. For example, if bytes_per_line is 749 8 and bytes_per_chunk is 4, the output will look like this: 750 00: 00000000 00000000 751 with the chunks displayed according to "display_endian". */ 752 753 if (info->section 754 && !(info->section->flags & SEC_CODE)) 755 { 756 /* This is not a CODE section. */ 757 switch (info->section->size) 758 { 759 case 1: 760 case 2: 761 case 4: 762 size = info->section->size; 763 break; 764 default: 765 size = (info->section->size & 0x01) ? 1 : 4; 766 break; 767 } 768 info->bytes_per_chunk = 1; 769 info->display_endian = info->endian; 770 } 771 else 772 { 773 size = 2; 774 info->bytes_per_chunk = 2; 775 info->display_endian = info->endian; 776 } 777 778 /* Read the insn into a host word. */ 779 status = (*info->read_memory_func) (memaddr, buffer, size, info); 780 if (status != 0) 781 { 782 (*info->memory_error_func) (status, memaddr, info); 783 return -1; 784 } 785 786 if (info->section 787 && !(info->section->flags & SEC_CODE)) 788 { 789 /* Data section. */ 790 unsigned long data; 791 792 data = bfd_get_bits (buffer, size * 8, 793 info->display_endian == BFD_ENDIAN_BIG); 794 switch (size) 795 { 796 case 1: 797 (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data); 798 break; 799 case 2: 800 (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data); 801 break; 802 case 4: 803 (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data); 804 break; 805 default: 806 abort (); 807 } 808 return size; 809 } 810 811 insn_len = arc_insn_length (buffer[lowbyte], buffer[highbyte], info); 812 pr_debug ("instruction length = %d bytes\n", insn_len); 813 switch (insn_len) 814 { 815 case 2: 816 insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte]; 817 break; 818 819 default: 820 /* An unknown instruction is treated as being length 4. This is 821 possibly not the best solution, but matches the behaviour that was 822 in place before the table based instruction length look-up was 823 introduced. */ 824 case 4: 825 /* This is a long instruction: Read the remaning 2 bytes. */ 826 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info); 827 if (status != 0) 828 { 829 (*info->memory_error_func) (status, memaddr + 2, info); 830 return -1; 831 } 832 insn[0] = ARRANGE_ENDIAN (info, buffer); 833 break; 834 } 835 836 /* Set some defaults for the insn info. */ 837 info->insn_info_valid = 1; 838 info->branch_delay_insns = 0; 839 info->data_size = 0; 840 info->insn_type = dis_nonbranch; 841 info->target = 0; 842 info->target2 = 0; 843 844 /* FIXME to be moved in dissasemble_init_for_target. */ 845 info->disassembler_needs_relocs = TRUE; 846 847 /* Find the first match in the opcode table. */ 848 if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter)) 849 return -1; 850 851 if (!opcode) 852 { 853 if (insn_len == 2) 854 (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]); 855 else 856 (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]); 857 858 info->insn_type = dis_noninsn; 859 return insn_len; 860 } 861 862 /* Print the mnemonic. */ 863 (*info->fprintf_func) (info->stream, "%s", opcode->name); 864 865 /* Preselect the insn class. */ 866 switch (opcode->insn_class) 867 { 868 case BRANCH: 869 case JUMP: 870 if (!strncmp (opcode->name, "bl", 2) 871 || !strncmp (opcode->name, "jl", 2)) 872 { 873 if (opcode->subclass == COND) 874 info->insn_type = dis_condjsr; 875 else 876 info->insn_type = dis_jsr; 877 } 878 else 879 { 880 if (opcode->subclass == COND) 881 info->insn_type = dis_condbranch; 882 else 883 info->insn_type = dis_branch; 884 } 885 break; 886 case MEMORY: 887 info->insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */ 888 break; 889 default: 890 info->insn_type = dis_nonbranch; 891 break; 892 } 893 894 pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode); 895 896 print_flags (opcode, insn, info); 897 898 if (opcode->operands[0] != 0) 899 (*info->fprintf_func) (info->stream, "\t"); 900 901 need_comma = FALSE; 902 open_braket = FALSE; 903 904 /* Now extract and print the operands. */ 905 operand = NULL; 906 while (operand_iterator_next (&iter, &operand, &value)) 907 { 908 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET)) 909 { 910 (*info->fprintf_func) (info->stream, "]"); 911 open_braket = FALSE; 912 continue; 913 } 914 915 /* Only take input from real operands. */ 916 if ((operand->flags & ARC_OPERAND_FAKE) 917 && !(operand->flags & ARC_OPERAND_BRAKET)) 918 continue; 919 920 if ((operand->flags & ARC_OPERAND_IGNORE) 921 && (operand->flags & ARC_OPERAND_IR) 922 && value == -1) 923 continue; 924 925 if (need_comma) 926 (*info->fprintf_func) (info->stream, ","); 927 928 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET)) 929 { 930 (*info->fprintf_func) (info->stream, "["); 931 open_braket = TRUE; 932 need_comma = FALSE; 933 continue; 934 } 935 936 /* Print the operand as directed by the flags. */ 937 if (operand->flags & ARC_OPERAND_IR) 938 { 939 const char *rname; 940 941 assert (value >=0 && value < 64); 942 rname = arcExtMap_coreRegName (value); 943 if (!rname) 944 rname = regnames[value]; 945 (*info->fprintf_func) (info->stream, "%s", rname); 946 if (operand->flags & ARC_OPERAND_TRUNCATE) 947 { 948 rname = arcExtMap_coreRegName (value + 1); 949 if (!rname) 950 rname = regnames[value + 1]; 951 (*info->fprintf_func) (info->stream, "%s", rname); 952 } 953 } 954 else if (operand->flags & ARC_OPERAND_LIMM) 955 { 956 const char *rname = get_auxreg (opcode, value, isa_mask); 957 if (rname && open_braket) 958 (*info->fprintf_func) (info->stream, "%s", rname); 959 else 960 { 961 (*info->fprintf_func) (info->stream, "%#x", value); 962 if (info->insn_type == dis_branch 963 || info->insn_type == dis_jsr) 964 info->target = (bfd_vma) value; 965 } 966 } 967 else if (operand->flags & ARC_OPERAND_PCREL) 968 { 969 /* PCL relative. */ 970 if (info->flags & INSN_HAS_RELOC) 971 memaddr = 0; 972 (*info->print_address_func) ((memaddr & ~3) + value, info); 973 974 info->target = (bfd_vma) (memaddr & ~3) + value; 975 } 976 else if (operand->flags & ARC_OPERAND_SIGNED) 977 { 978 const char *rname = get_auxreg (opcode, value, isa_mask); 979 if (rname && open_braket) 980 (*info->fprintf_func) (info->stream, "%s", rname); 981 else 982 (*info->fprintf_func) (info->stream, "%d", value); 983 } 984 else 985 { 986 if (operand->flags & ARC_OPERAND_TRUNCATE 987 && !(operand->flags & ARC_OPERAND_ALIGNED32) 988 && !(operand->flags & ARC_OPERAND_ALIGNED16) 989 && value > 0 && value <= 14) 990 (*info->fprintf_func) (info->stream, "r13-%s", 991 regnames[13 + value - 1]); 992 else 993 { 994 const char *rname = get_auxreg (opcode, value, isa_mask); 995 if (rname && open_braket) 996 (*info->fprintf_func) (info->stream, "%s", rname); 997 else 998 (*info->fprintf_func) (info->stream, "%#x", value); 999 } 1000 } 1001 1002 need_comma = TRUE; 1003 } 1004 1005 return insn_len; 1006 } 1007 1008 1009 disassembler_ftype 1010 arc_get_disassembler (bfd *abfd) 1011 { 1012 /* Read the extenssion insns and registers, if any. */ 1013 build_ARC_extmap (abfd); 1014 #ifdef DEBUG 1015 dump_ARC_extmap (); 1016 #endif 1017 1018 return print_insn_arc; 1019 } 1020 1021 /* Disassemble ARC instructions. Used by debugger. */ 1022 1023 struct arcDisState 1024 arcAnalyzeInstr (bfd_vma memaddr, 1025 struct disassemble_info *info) 1026 { 1027 struct arcDisState ret; 1028 memset (&ret, 0, sizeof (struct arcDisState)); 1029 1030 ret.instructionLen = print_insn_arc (memaddr, info); 1031 1032 #if 0 1033 ret.words[0] = insn[0]; 1034 ret.words[1] = insn[1]; 1035 ret._this = &ret; 1036 ret.coreRegName = _coreRegName; 1037 ret.auxRegName = _auxRegName; 1038 ret.condCodeName = _condCodeName; 1039 ret.instName = _instName; 1040 #endif 1041 1042 return ret; 1043 } 1044 1045 /* Local variables: 1046 eval: (c-set-style "gnu") 1047 indent-tabs-mode: t 1048 End: */ 1049