1 /* Instruction printing code for the ARC. 2 Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005 3 Free Software Foundation, Inc. 4 Contributed by Doug Evans (dje@cygnus.com). 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 #include "ansidecl.h" 22 #include "libiberty.h" 23 #include "dis-asm.h" 24 #include "opcode/arc.h" 25 #include "elf-bfd.h" 26 #include "elf/arc.h" 27 #include <string.h> 28 #include "opintl.h" 29 30 #include <stdarg.h> 31 #include "arc-dis.h" 32 #include "arc-ext.h" 33 34 #ifndef dbg 35 #define dbg (0) 36 #endif 37 38 /* Classification of the opcodes for the decoder to print 39 the instructions. */ 40 41 typedef enum 42 { 43 CLASS_A4_ARITH, 44 CLASS_A4_OP3_GENERAL, 45 CLASS_A4_FLAG, 46 /* All branches other than JC. */ 47 CLASS_A4_BRANCH, 48 CLASS_A4_JC , 49 /* All loads other than immediate 50 indexed loads. */ 51 CLASS_A4_LD0, 52 CLASS_A4_LD1, 53 CLASS_A4_ST, 54 CLASS_A4_SR, 55 /* All single operand instructions. */ 56 CLASS_A4_OP3_SUBOPC3F, 57 CLASS_A4_LR 58 } a4_decoding_class; 59 60 #define BIT(word,n) ((word) & (1 << n)) 61 #define BITS(word,s,e) (((word) << (31 - e)) >> (s + (31 - e))) 62 #define OPCODE(word) (BITS ((word), 27, 31)) 63 #define FIELDA(word) (BITS ((word), 21, 26)) 64 #define FIELDB(word) (BITS ((word), 15, 20)) 65 #define FIELDC(word) (BITS ((word), 9, 14)) 66 67 /* FIELD D is signed in all of its uses, so we make sure argument is 68 treated as signed for bit shifting purposes: */ 69 #define FIELDD(word) (BITS (((signed int)word), 0, 8)) 70 71 #define PUT_NEXT_WORD_IN(a) \ 72 do \ 73 { \ 74 if (is_limm == 1 && !NEXT_WORD (1)) \ 75 mwerror (state, _("Illegal limm reference in last instruction!\n")); \ 76 a = state->words[1]; \ 77 } \ 78 while (0) 79 80 #define CHECK_FLAG_COND_NULLIFY() \ 81 do \ 82 { \ 83 if (is_shimm == 0) \ 84 { \ 85 flag = BIT (state->words[0], 8); \ 86 state->nullifyMode = BITS (state->words[0], 5, 6); \ 87 cond = BITS (state->words[0], 0, 4); \ 88 } \ 89 } \ 90 while (0) 91 92 #define CHECK_COND() \ 93 do \ 94 { \ 95 if (is_shimm == 0) \ 96 cond = BITS (state->words[0], 0, 4); \ 97 } \ 98 while (0) 99 100 #define CHECK_FIELD(field) \ 101 do \ 102 { \ 103 if (field == 62) \ 104 { \ 105 is_limm++; \ 106 field##isReg = 0; \ 107 PUT_NEXT_WORD_IN (field); \ 108 limm_value = field; \ 109 } \ 110 else if (field > 60) \ 111 { \ 112 field##isReg = 0; \ 113 is_shimm++; \ 114 flag = (field == 61); \ 115 field = FIELDD (state->words[0]); \ 116 } \ 117 } \ 118 while (0) 119 120 #define CHECK_FIELD_A() \ 121 do \ 122 { \ 123 fieldA = FIELDA (state->words[0]); \ 124 if (fieldA > 60) \ 125 { \ 126 fieldAisReg = 0; \ 127 fieldA = 0; \ 128 } \ 129 } \ 130 while (0) 131 132 #define CHECK_FIELD_B() \ 133 do \ 134 { \ 135 fieldB = FIELDB (state->words[0]); \ 136 CHECK_FIELD (fieldB); \ 137 } \ 138 while (0) 139 140 #define CHECK_FIELD_C() \ 141 do \ 142 { \ 143 fieldC = FIELDC (state->words[0]); \ 144 CHECK_FIELD (fieldC); \ 145 } \ 146 while (0) 147 148 #define IS_SMALL(x) (((field##x) < 256) && ((field##x) > -257)) 149 #define IS_REG(x) (field##x##isReg) 150 #define WRITE_FORMAT_LB_Rx_RB(x) WRITE_FORMAT (x, "[","]","","") 151 #define WRITE_FORMAT_x_COMMA_LB(x) WRITE_FORMAT (x, "",",[","",",[") 152 #define WRITE_FORMAT_COMMA_x_RB(x) WRITE_FORMAT (x, ",","]",",","]") 153 #define WRITE_FORMAT_x_RB(x) WRITE_FORMAT (x, "","]","","]") 154 #define WRITE_FORMAT_COMMA_x(x) WRITE_FORMAT (x, ",","",",","") 155 #define WRITE_FORMAT_x_COMMA(x) WRITE_FORMAT (x, "",",","",",") 156 #define WRITE_FORMAT_x(x) WRITE_FORMAT (x, "","","","") 157 #define WRITE_FORMAT(x,cb1,ca1,cb,ca) strcat (formatString, \ 158 (IS_REG (x) ? cb1"%r"ca1 : \ 159 usesAuxReg ? cb"%a"ca : \ 160 IS_SMALL (x) ? cb"%d"ca : cb"%h"ca)) 161 #define WRITE_FORMAT_RB() strcat (formatString, "]") 162 #define WRITE_COMMENT(str) (state->comm[state->commNum++] = (str)) 163 #define WRITE_NOP_COMMENT() if (!fieldAisReg && !flag) WRITE_COMMENT ("nop"); 164 165 #define NEXT_WORD(x) (offset += 4, state->words[x]) 166 167 #define add_target(x) (state->targets[state->tcnt++] = (x)) 168 169 static char comment_prefix[] = "\t; "; 170 171 static const char * 172 core_reg_name (struct arcDisState * state, int val) 173 { 174 if (state->coreRegName) 175 return (*state->coreRegName)(state->_this, val); 176 return 0; 177 } 178 179 static const char * 180 aux_reg_name (struct arcDisState * state, int val) 181 { 182 if (state->auxRegName) 183 return (*state->auxRegName)(state->_this, val); 184 return 0; 185 } 186 187 static const char * 188 cond_code_name (struct arcDisState * state, int val) 189 { 190 if (state->condCodeName) 191 return (*state->condCodeName)(state->_this, val); 192 return 0; 193 } 194 195 static const char * 196 instruction_name (struct arcDisState * state, 197 int op1, 198 int op2, 199 int * flags) 200 { 201 if (state->instName) 202 return (*state->instName)(state->_this, op1, op2, flags); 203 return 0; 204 } 205 206 static void 207 mwerror (struct arcDisState * state, const char * msg) 208 { 209 if (state->err != 0) 210 (*state->err)(state->_this, (msg)); 211 } 212 213 static const char * 214 post_address (struct arcDisState * state, int addr) 215 { 216 static char id[3 * ARRAY_SIZE (state->addresses)]; 217 int j, i = state->acnt; 218 219 if (i < ((int) ARRAY_SIZE (state->addresses))) 220 { 221 state->addresses[i] = addr; 222 ++state->acnt; 223 j = i*3; 224 id[j+0] = '@'; 225 id[j+1] = '0'+i; 226 id[j+2] = 0; 227 228 return id + j; 229 } 230 return ""; 231 } 232 233 static void 234 arc_sprintf (struct arcDisState *state, char *buf, const char *format, ...) 235 { 236 char *bp; 237 const char *p; 238 int size, leading_zero, regMap[2]; 239 long auxNum; 240 va_list ap; 241 242 va_start (ap, format); 243 244 bp = buf; 245 *bp = 0; 246 p = format; 247 auxNum = -1; 248 regMap[0] = 0; 249 regMap[1] = 0; 250 251 while (1) 252 switch (*p++) 253 { 254 case 0: 255 goto DOCOMM; /* (return) */ 256 default: 257 *bp++ = p[-1]; 258 break; 259 case '%': 260 size = 0; 261 leading_zero = 0; 262 RETRY: ; 263 switch (*p++) 264 { 265 case '0': 266 case '1': 267 case '2': 268 case '3': 269 case '4': 270 case '5': 271 case '6': 272 case '7': 273 case '8': 274 case '9': 275 { 276 /* size. */ 277 size = p[-1] - '0'; 278 if (size == 0) 279 leading_zero = 1; /* e.g. %08x */ 280 while (*p >= '0' && *p <= '9') 281 { 282 size = size * 10 + *p - '0'; 283 p++; 284 } 285 goto RETRY; 286 } 287 #define inc_bp() bp = bp + strlen (bp) 288 289 case 'h': 290 { 291 unsigned u = va_arg (ap, int); 292 293 /* Hex. We can change the format to 0x%08x in 294 one place, here, if we wish. 295 We add underscores for easy reading. */ 296 if (u > 65536) 297 sprintf (bp, "0x%x_%04x", u >> 16, u & 0xffff); 298 else 299 sprintf (bp, "0x%x", u); 300 inc_bp (); 301 } 302 break; 303 case 'X': case 'x': 304 { 305 int val = va_arg (ap, int); 306 307 if (size != 0) 308 if (leading_zero) 309 sprintf (bp, "%0*x", size, val); 310 else 311 sprintf (bp, "%*x", size, val); 312 else 313 sprintf (bp, "%x", val); 314 inc_bp (); 315 } 316 break; 317 case 'd': 318 { 319 int val = va_arg (ap, int); 320 321 if (size != 0) 322 sprintf (bp, "%*d", size, val); 323 else 324 sprintf (bp, "%d", val); 325 inc_bp (); 326 } 327 break; 328 case 'r': 329 { 330 /* Register. */ 331 int val = va_arg (ap, int); 332 333 #define REG2NAME(num, name) case num: sprintf (bp, ""name); \ 334 regMap[(num < 32) ? 0 : 1] |= 1 << (num - ((num < 32) ? 0 : 32)); break; 335 336 switch (val) 337 { 338 REG2NAME (26, "gp"); 339 REG2NAME (27, "fp"); 340 REG2NAME (28, "sp"); 341 REG2NAME (29, "ilink1"); 342 REG2NAME (30, "ilink2"); 343 REG2NAME (31, "blink"); 344 REG2NAME (60, "lp_count"); 345 default: 346 { 347 const char * ext; 348 349 ext = core_reg_name (state, val); 350 if (ext) 351 sprintf (bp, "%s", ext); 352 else 353 sprintf (bp,"r%d",val); 354 } 355 break; 356 } 357 inc_bp (); 358 } break; 359 360 case 'a': 361 { 362 /* Aux Register. */ 363 int val = va_arg (ap, int); 364 365 #define AUXREG2NAME(num, name) case num: sprintf (bp,name); break; 366 367 switch (val) 368 { 369 AUXREG2NAME (0x0, "status"); 370 AUXREG2NAME (0x1, "semaphore"); 371 AUXREG2NAME (0x2, "lp_start"); 372 AUXREG2NAME (0x3, "lp_end"); 373 AUXREG2NAME (0x4, "identity"); 374 AUXREG2NAME (0x5, "debug"); 375 default: 376 { 377 const char *ext; 378 379 ext = aux_reg_name (state, val); 380 if (ext) 381 sprintf (bp, "%s", ext); 382 else 383 arc_sprintf (state, bp, "%h", val); 384 } 385 break; 386 } 387 inc_bp (); 388 } 389 break; 390 391 case 's': 392 { 393 sprintf (bp, "%s", va_arg (ap, char *)); 394 inc_bp (); 395 } 396 break; 397 398 default: 399 fprintf (stderr, "?? format %c\n", p[-1]); 400 break; 401 } 402 } 403 404 DOCOMM: *bp = 0; 405 va_end (ap); 406 } 407 408 static void 409 write_comments_(struct arcDisState * state, 410 int shimm, 411 int is_limm, 412 long limm_value) 413 { 414 if (state->commentBuffer != 0) 415 { 416 int i; 417 418 if (is_limm) 419 { 420 const char *name = post_address (state, limm_value + shimm); 421 422 if (*name != 0) 423 WRITE_COMMENT (name); 424 } 425 for (i = 0; i < state->commNum; i++) 426 { 427 if (i == 0) 428 strcpy (state->commentBuffer, comment_prefix); 429 else 430 strcat (state->commentBuffer, ", "); 431 strncat (state->commentBuffer, state->comm[i], 432 sizeof (state->commentBuffer)); 433 } 434 } 435 } 436 437 #define write_comments2(x) write_comments_ (state, x, is_limm, limm_value) 438 #define write_comments() write_comments2 (0) 439 440 static const char *condName[] = 441 { 442 /* 0..15. */ 443 "" , "z" , "nz" , "p" , "n" , "c" , "nc" , "v" , 444 "nv" , "gt" , "ge" , "lt" , "le" , "hi" , "ls" , "pnz" 445 }; 446 447 static void 448 write_instr_name_(struct arcDisState * state, 449 const char * instrName, 450 int cond, 451 int condCodeIsPartOfName, 452 int flag, 453 int signExtend, 454 int addrWriteBack, 455 int directMem) 456 { 457 strcpy (state->instrBuffer, instrName); 458 459 if (cond > 0) 460 { 461 const char *cc = 0; 462 463 if (!condCodeIsPartOfName) 464 strcat (state->instrBuffer, "."); 465 466 if (cond < 16) 467 cc = condName[cond]; 468 else 469 cc = cond_code_name (state, cond); 470 471 if (!cc) 472 cc = "???"; 473 474 strcat (state->instrBuffer, cc); 475 } 476 477 if (flag) 478 strcat (state->instrBuffer, ".f"); 479 480 switch (state->nullifyMode) 481 { 482 case BR_exec_always: 483 strcat (state->instrBuffer, ".d"); 484 break; 485 case BR_exec_when_jump: 486 strcat (state->instrBuffer, ".jd"); 487 break; 488 } 489 490 if (signExtend) 491 strcat (state->instrBuffer, ".x"); 492 493 if (addrWriteBack) 494 strcat (state->instrBuffer, ".a"); 495 496 if (directMem) 497 strcat (state->instrBuffer, ".di"); 498 } 499 500 #define write_instr_name() \ 501 do \ 502 { \ 503 write_instr_name_(state, instrName,cond, condCodeIsPartOfName, \ 504 flag, signExtend, addrWriteBack, directMem); \ 505 formatString[0] = '\0'; \ 506 } \ 507 while (0) 508 509 enum 510 { 511 op_LD0 = 0, op_LD1 = 1, op_ST = 2, op_3 = 3, 512 op_BC = 4, op_BLC = 5, op_LPC = 6, op_JC = 7, 513 op_ADD = 8, op_ADC = 9, op_SUB = 10, op_SBC = 11, 514 op_AND = 12, op_OR = 13, op_BIC = 14, op_XOR = 15 515 }; 516 517 extern disassemble_info tm_print_insn_info; 518 519 static int 520 dsmOneArcInst (bfd_vma addr, struct arcDisState * state) 521 { 522 int condCodeIsPartOfName = 0; 523 a4_decoding_class decodingClass; 524 const char * instrName; 525 int repeatsOp = 0; 526 int fieldAisReg = 1; 527 int fieldBisReg = 1; 528 int fieldCisReg = 1; 529 int fieldA; 530 int fieldB; 531 int fieldC = 0; 532 int flag = 0; 533 int cond = 0; 534 int is_shimm = 0; 535 int is_limm = 0; 536 long limm_value = 0; 537 int signExtend = 0; 538 int addrWriteBack = 0; 539 int directMem = 0; 540 int is_linked = 0; 541 int offset = 0; 542 int usesAuxReg = 0; 543 int flags; 544 int ignoreFirstOpd; 545 char formatString[60]; 546 547 state->instructionLen = 4; 548 state->nullifyMode = BR_exec_when_no_jump; 549 state->opWidth = 12; 550 state->isBranch = 0; 551 552 state->_mem_load = 0; 553 state->_ea_present = 0; 554 state->_load_len = 0; 555 state->ea_reg1 = no_reg; 556 state->ea_reg2 = no_reg; 557 state->_offset = 0; 558 559 if (! NEXT_WORD (0)) 560 return 0; 561 562 state->_opcode = OPCODE (state->words[0]); 563 instrName = 0; 564 decodingClass = CLASS_A4_ARITH; /* default! */ 565 repeatsOp = 0; 566 condCodeIsPartOfName=0; 567 state->commNum = 0; 568 state->tcnt = 0; 569 state->acnt = 0; 570 state->flow = noflow; 571 ignoreFirstOpd = 0; 572 573 if (state->commentBuffer) 574 state->commentBuffer[0] = '\0'; 575 576 switch (state->_opcode) 577 { 578 case op_LD0: 579 switch (BITS (state->words[0],1,2)) 580 { 581 case 0: 582 instrName = "ld"; 583 state->_load_len = 4; 584 break; 585 case 1: 586 instrName = "ldb"; 587 state->_load_len = 1; 588 break; 589 case 2: 590 instrName = "ldw"; 591 state->_load_len = 2; 592 break; 593 default: 594 instrName = "??? (0[3])"; 595 state->flow = invalid_instr; 596 break; 597 } 598 decodingClass = CLASS_A4_LD0; 599 break; 600 601 case op_LD1: 602 if (BIT (state->words[0],13)) 603 { 604 instrName = "lr"; 605 decodingClass = CLASS_A4_LR; 606 } 607 else 608 { 609 switch (BITS (state->words[0], 10, 11)) 610 { 611 case 0: 612 instrName = "ld"; 613 state->_load_len = 4; 614 break; 615 case 1: 616 instrName = "ldb"; 617 state->_load_len = 1; 618 break; 619 case 2: 620 instrName = "ldw"; 621 state->_load_len = 2; 622 break; 623 default: 624 instrName = "??? (1[3])"; 625 state->flow = invalid_instr; 626 break; 627 } 628 decodingClass = CLASS_A4_LD1; 629 } 630 break; 631 632 case op_ST: 633 if (BIT (state->words[0], 25)) 634 { 635 instrName = "sr"; 636 decodingClass = CLASS_A4_SR; 637 } 638 else 639 { 640 switch (BITS (state->words[0], 22, 23)) 641 { 642 case 0: 643 instrName = "st"; 644 break; 645 case 1: 646 instrName = "stb"; 647 break; 648 case 2: 649 instrName = "stw"; 650 break; 651 default: 652 instrName = "??? (2[3])"; 653 state->flow = invalid_instr; 654 break; 655 } 656 decodingClass = CLASS_A4_ST; 657 } 658 break; 659 660 case op_3: 661 decodingClass = CLASS_A4_OP3_GENERAL; /* default for opcode 3... */ 662 switch (FIELDC (state->words[0])) 663 { 664 case 0: 665 instrName = "flag"; 666 decodingClass = CLASS_A4_FLAG; 667 break; 668 case 1: 669 instrName = "asr"; 670 break; 671 case 2: 672 instrName = "lsr"; 673 break; 674 case 3: 675 instrName = "ror"; 676 break; 677 case 4: 678 instrName = "rrc"; 679 break; 680 case 5: 681 instrName = "sexb"; 682 break; 683 case 6: 684 instrName = "sexw"; 685 break; 686 case 7: 687 instrName = "extb"; 688 break; 689 case 8: 690 instrName = "extw"; 691 break; 692 case 0x3f: 693 { 694 decodingClass = CLASS_A4_OP3_SUBOPC3F; 695 switch (FIELDD (state->words[0])) 696 { 697 case 0: 698 instrName = "brk"; 699 break; 700 case 1: 701 instrName = "sleep"; 702 break; 703 case 2: 704 instrName = "swi"; 705 break; 706 default: 707 instrName = "???"; 708 state->flow=invalid_instr; 709 break; 710 } 711 } 712 break; 713 714 /* ARC Extension Library Instructions 715 NOTE: We assume that extension codes are these instrs. */ 716 default: 717 instrName = instruction_name (state, 718 state->_opcode, 719 FIELDC (state->words[0]), 720 &flags); 721 if (!instrName) 722 { 723 instrName = "???"; 724 state->flow = invalid_instr; 725 } 726 if (flags & IGNORE_FIRST_OPD) 727 ignoreFirstOpd = 1; 728 break; 729 } 730 break; 731 732 case op_BC: 733 instrName = "b"; 734 case op_BLC: 735 if (!instrName) 736 instrName = "bl"; 737 case op_LPC: 738 if (!instrName) 739 instrName = "lp"; 740 case op_JC: 741 if (!instrName) 742 { 743 if (BITS (state->words[0],9,9)) 744 { 745 instrName = "jl"; 746 is_linked = 1; 747 } 748 else 749 { 750 instrName = "j"; 751 is_linked = 0; 752 } 753 } 754 condCodeIsPartOfName = 1; 755 decodingClass = ((state->_opcode == op_JC) ? CLASS_A4_JC : CLASS_A4_BRANCH ); 756 state->isBranch = 1; 757 break; 758 759 case op_ADD: 760 case op_ADC: 761 case op_AND: 762 repeatsOp = (FIELDC (state->words[0]) == FIELDB (state->words[0])); 763 764 switch (state->_opcode) 765 { 766 case op_ADD: 767 instrName = (repeatsOp ? "asl" : "add"); 768 break; 769 case op_ADC: 770 instrName = (repeatsOp ? "rlc" : "adc"); 771 break; 772 case op_AND: 773 instrName = (repeatsOp ? "mov" : "and"); 774 break; 775 } 776 break; 777 778 case op_SUB: instrName = "sub"; 779 break; 780 case op_SBC: instrName = "sbc"; 781 break; 782 case op_OR: instrName = "or"; 783 break; 784 case op_BIC: instrName = "bic"; 785 break; 786 787 case op_XOR: 788 if (state->words[0] == 0x7fffffff) 789 { 790 /* NOP encoded as xor -1, -1, -1. */ 791 instrName = "nop"; 792 decodingClass = CLASS_A4_OP3_SUBOPC3F; 793 } 794 else 795 instrName = "xor"; 796 break; 797 798 default: 799 instrName = instruction_name (state,state->_opcode,0,&flags); 800 /* if (instrName) printf("FLAGS=0x%x\n", flags); */ 801 if (!instrName) 802 { 803 instrName = "???"; 804 state->flow=invalid_instr; 805 } 806 if (flags & IGNORE_FIRST_OPD) 807 ignoreFirstOpd = 1; 808 break; 809 } 810 811 fieldAisReg = fieldBisReg = fieldCisReg = 1; /* Assume regs for now. */ 812 flag = cond = is_shimm = is_limm = 0; 813 state->nullifyMode = BR_exec_when_no_jump; /* 0 */ 814 signExtend = addrWriteBack = directMem = 0; 815 usesAuxReg = 0; 816 817 switch (decodingClass) 818 { 819 case CLASS_A4_ARITH: 820 CHECK_FIELD_A (); 821 CHECK_FIELD_B (); 822 if (!repeatsOp) 823 CHECK_FIELD_C (); 824 CHECK_FLAG_COND_NULLIFY (); 825 826 write_instr_name (); 827 if (!ignoreFirstOpd) 828 { 829 WRITE_FORMAT_x (A); 830 WRITE_FORMAT_COMMA_x (B); 831 if (!repeatsOp) 832 WRITE_FORMAT_COMMA_x (C); 833 WRITE_NOP_COMMENT (); 834 arc_sprintf (state, state->operandBuffer, formatString, 835 fieldA, fieldB, fieldC); 836 } 837 else 838 { 839 WRITE_FORMAT_x (B); 840 if (!repeatsOp) 841 WRITE_FORMAT_COMMA_x (C); 842 arc_sprintf (state, state->operandBuffer, formatString, 843 fieldB, fieldC); 844 } 845 write_comments (); 846 break; 847 848 case CLASS_A4_OP3_GENERAL: 849 CHECK_FIELD_A (); 850 CHECK_FIELD_B (); 851 CHECK_FLAG_COND_NULLIFY (); 852 853 write_instr_name (); 854 if (!ignoreFirstOpd) 855 { 856 WRITE_FORMAT_x (A); 857 WRITE_FORMAT_COMMA_x (B); 858 WRITE_NOP_COMMENT (); 859 arc_sprintf (state, state->operandBuffer, formatString, 860 fieldA, fieldB); 861 } 862 else 863 { 864 WRITE_FORMAT_x (B); 865 arc_sprintf (state, state->operandBuffer, formatString, fieldB); 866 } 867 write_comments (); 868 break; 869 870 case CLASS_A4_FLAG: 871 CHECK_FIELD_B (); 872 CHECK_FLAG_COND_NULLIFY (); 873 flag = 0; /* This is the FLAG instruction -- it's redundant. */ 874 875 write_instr_name (); 876 WRITE_FORMAT_x (B); 877 arc_sprintf (state, state->operandBuffer, formatString, fieldB); 878 write_comments (); 879 break; 880 881 case CLASS_A4_BRANCH: 882 fieldA = BITS (state->words[0],7,26) << 2; 883 fieldA = (fieldA << 10) >> 10; /* Make it signed. */ 884 fieldA += addr + 4; 885 CHECK_FLAG_COND_NULLIFY (); 886 flag = 0; 887 888 write_instr_name (); 889 /* This address could be a label we know. Convert it. */ 890 if (state->_opcode != op_LPC /* LP */) 891 { 892 add_target (fieldA); /* For debugger. */ 893 state->flow = state->_opcode == op_BLC /* BL */ 894 ? direct_call 895 : direct_jump; 896 /* indirect calls are achieved by "lr blink,[status]; 897 lr dest<- func addr; j [dest]" */ 898 } 899 900 strcat (formatString, "%s"); /* Address/label name. */ 901 arc_sprintf (state, state->operandBuffer, formatString, 902 post_address (state, fieldA)); 903 write_comments (); 904 break; 905 906 case CLASS_A4_JC: 907 /* For op_JC -- jump to address specified. 908 Also covers jump and link--bit 9 of the instr. word 909 selects whether linked, thus "is_linked" is set above. */ 910 fieldA = 0; 911 CHECK_FIELD_B (); 912 CHECK_FLAG_COND_NULLIFY (); 913 914 if (!fieldBisReg) 915 { 916 fieldAisReg = 0; 917 fieldA = (fieldB >> 25) & 0x7F; /* Flags. */ 918 fieldB = (fieldB & 0xFFFFFF) << 2; 919 state->flow = is_linked ? direct_call : direct_jump; 920 add_target (fieldB); 921 /* Screwy JLcc requires .jd mode to execute correctly 922 but we pretend it is .nd (no delay slot). */ 923 if (is_linked && state->nullifyMode == BR_exec_when_jump) 924 state->nullifyMode = BR_exec_when_no_jump; 925 } 926 else 927 { 928 state->flow = is_linked ? indirect_call : indirect_jump; 929 /* We should also treat this as indirect call if NOT linked 930 but the preceding instruction was a "lr blink,[status]" 931 and we have a delay slot with "add blink,blink,2". 932 For now we can't detect such. */ 933 state->register_for_indirect_jump = fieldB; 934 } 935 936 write_instr_name (); 937 strcat (formatString, 938 IS_REG (B) ? "[%r]" : "%s"); /* Address/label name. */ 939 if (fieldA != 0) 940 { 941 fieldAisReg = 0; 942 WRITE_FORMAT_COMMA_x (A); 943 } 944 if (IS_REG (B)) 945 arc_sprintf (state, state->operandBuffer, formatString, fieldB, fieldA); 946 else 947 arc_sprintf (state, state->operandBuffer, formatString, 948 post_address (state, fieldB), fieldA); 949 write_comments (); 950 break; 951 952 case CLASS_A4_LD0: 953 /* LD instruction. 954 B and C can be regs, or one (both?) can be limm. */ 955 CHECK_FIELD_A (); 956 CHECK_FIELD_B (); 957 CHECK_FIELD_C (); 958 if (dbg) 959 printf ("5:b reg %d %d c reg %d %d \n", 960 fieldBisReg,fieldB,fieldCisReg,fieldC); 961 state->_offset = 0; 962 state->_ea_present = 1; 963 if (fieldBisReg) 964 state->ea_reg1 = fieldB; 965 else 966 state->_offset += fieldB; 967 if (fieldCisReg) 968 state->ea_reg2 = fieldC; 969 else 970 state->_offset += fieldC; 971 state->_mem_load = 1; 972 973 directMem = BIT (state->words[0], 5); 974 addrWriteBack = BIT (state->words[0], 3); 975 signExtend = BIT (state->words[0], 0); 976 977 write_instr_name (); 978 WRITE_FORMAT_x_COMMA_LB(A); 979 if (fieldBisReg || fieldB != 0) 980 WRITE_FORMAT_x_COMMA (B); 981 else 982 fieldB = fieldC; 983 984 WRITE_FORMAT_x_RB (C); 985 arc_sprintf (state, state->operandBuffer, formatString, 986 fieldA, fieldB, fieldC); 987 write_comments (); 988 break; 989 990 case CLASS_A4_LD1: 991 /* LD instruction. */ 992 CHECK_FIELD_B (); 993 CHECK_FIELD_A (); 994 fieldC = FIELDD (state->words[0]); 995 996 if (dbg) 997 printf ("6:b reg %d %d c 0x%x \n", 998 fieldBisReg, fieldB, fieldC); 999 state->_ea_present = 1; 1000 state->_offset = fieldC; 1001 state->_mem_load = 1; 1002 if (fieldBisReg) 1003 state->ea_reg1 = fieldB; 1004 /* Field B is either a shimm (same as fieldC) or limm (different!) 1005 Say ea is not present, so only one of us will do the name lookup. */ 1006 else 1007 state->_offset += fieldB, state->_ea_present = 0; 1008 1009 directMem = BIT (state->words[0],14); 1010 addrWriteBack = BIT (state->words[0],12); 1011 signExtend = BIT (state->words[0],9); 1012 1013 write_instr_name (); 1014 WRITE_FORMAT_x_COMMA_LB (A); 1015 if (!fieldBisReg) 1016 { 1017 fieldB = state->_offset; 1018 WRITE_FORMAT_x_RB (B); 1019 } 1020 else 1021 { 1022 WRITE_FORMAT_x (B); 1023 if (fieldC != 0 && !BIT (state->words[0],13)) 1024 { 1025 fieldCisReg = 0; 1026 WRITE_FORMAT_COMMA_x_RB (C); 1027 } 1028 else 1029 WRITE_FORMAT_RB (); 1030 } 1031 arc_sprintf (state, state->operandBuffer, formatString, 1032 fieldA, fieldB, fieldC); 1033 write_comments (); 1034 break; 1035 1036 case CLASS_A4_ST: 1037 /* ST instruction. */ 1038 CHECK_FIELD_B(); 1039 CHECK_FIELD_C(); 1040 fieldA = FIELDD(state->words[0]); /* shimm */ 1041 1042 /* [B,A offset] */ 1043 if (dbg) printf("7:b reg %d %x off %x\n", 1044 fieldBisReg,fieldB,fieldA); 1045 state->_ea_present = 1; 1046 state->_offset = fieldA; 1047 if (fieldBisReg) 1048 state->ea_reg1 = fieldB; 1049 /* Field B is either a shimm (same as fieldA) or limm (different!) 1050 Say ea is not present, so only one of us will do the name lookup. 1051 (for is_limm we do the name translation here). */ 1052 else 1053 state->_offset += fieldB, state->_ea_present = 0; 1054 1055 directMem = BIT (state->words[0], 26); 1056 addrWriteBack = BIT (state->words[0], 24); 1057 1058 write_instr_name (); 1059 WRITE_FORMAT_x_COMMA_LB(C); 1060 1061 if (!fieldBisReg) 1062 { 1063 fieldB = state->_offset; 1064 WRITE_FORMAT_x_RB (B); 1065 } 1066 else 1067 { 1068 WRITE_FORMAT_x (B); 1069 if (fieldBisReg && fieldA != 0) 1070 { 1071 fieldAisReg = 0; 1072 WRITE_FORMAT_COMMA_x_RB(A); 1073 } 1074 else 1075 WRITE_FORMAT_RB(); 1076 } 1077 arc_sprintf (state, state->operandBuffer, formatString, 1078 fieldC, fieldB, fieldA); 1079 write_comments2 (fieldA); 1080 break; 1081 1082 case CLASS_A4_SR: 1083 /* SR instruction */ 1084 CHECK_FIELD_B(); 1085 CHECK_FIELD_C(); 1086 1087 write_instr_name (); 1088 WRITE_FORMAT_x_COMMA_LB(C); 1089 /* Try to print B as an aux reg if it is not a core reg. */ 1090 usesAuxReg = 1; 1091 WRITE_FORMAT_x (B); 1092 WRITE_FORMAT_RB (); 1093 arc_sprintf (state, state->operandBuffer, formatString, fieldC, fieldB); 1094 write_comments (); 1095 break; 1096 1097 case CLASS_A4_OP3_SUBOPC3F: 1098 write_instr_name (); 1099 state->operandBuffer[0] = '\0'; 1100 break; 1101 1102 case CLASS_A4_LR: 1103 /* LR instruction */ 1104 CHECK_FIELD_A (); 1105 CHECK_FIELD_B (); 1106 1107 write_instr_name (); 1108 WRITE_FORMAT_x_COMMA_LB (A); 1109 /* Try to print B as an aux reg if it is not a core reg. */ 1110 usesAuxReg = 1; 1111 WRITE_FORMAT_x (B); 1112 WRITE_FORMAT_RB (); 1113 arc_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB); 1114 write_comments (); 1115 break; 1116 1117 default: 1118 mwerror (state, "Bad decoding class in ARC disassembler"); 1119 break; 1120 } 1121 1122 state->_cond = cond; 1123 return state->instructionLen = offset; 1124 } 1125 1126 1127 /* Returns the name the user specified core extension register. */ 1128 1129 static const char * 1130 _coreRegName(void * arg ATTRIBUTE_UNUSED, int regval) 1131 { 1132 return arcExtMap_coreRegName (regval); 1133 } 1134 1135 /* Returns the name the user specified AUX extension register. */ 1136 1137 static const char * 1138 _auxRegName(void *_this ATTRIBUTE_UNUSED, int regval) 1139 { 1140 return arcExtMap_auxRegName(regval); 1141 } 1142 1143 /* Returns the name the user specified condition code name. */ 1144 1145 static const char * 1146 _condCodeName(void *_this ATTRIBUTE_UNUSED, int regval) 1147 { 1148 return arcExtMap_condCodeName(regval); 1149 } 1150 1151 /* Returns the name the user specified extension instruction. */ 1152 1153 static const char * 1154 _instName (void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags) 1155 { 1156 return arcExtMap_instName(majop, minop, flags); 1157 } 1158 1159 /* Decode an instruction returning the size of the instruction 1160 in bytes or zero if unrecognized. */ 1161 1162 static int 1163 decodeInstr (bfd_vma address, /* Address of this instruction. */ 1164 disassemble_info * info) 1165 { 1166 int status; 1167 bfd_byte buffer[4]; 1168 struct arcDisState s; /* ARC Disassembler state. */ 1169 void *stream = info->stream; /* Output stream. */ 1170 fprintf_ftype func = info->fprintf_func; 1171 int bytes; 1172 1173 memset (&s, 0, sizeof(struct arcDisState)); 1174 1175 /* read first instruction */ 1176 status = (*info->read_memory_func) (address, buffer, 4, info); 1177 if (status != 0) 1178 { 1179 (*info->memory_error_func) (status, address, info); 1180 return 0; 1181 } 1182 if (info->endian == BFD_ENDIAN_LITTLE) 1183 s.words[0] = bfd_getl32(buffer); 1184 else 1185 s.words[0] = bfd_getb32(buffer); 1186 /* Always read second word in case of limm. */ 1187 1188 /* We ignore the result since last insn may not have a limm. */ 1189 status = (*info->read_memory_func) (address + 4, buffer, 4, info); 1190 if (info->endian == BFD_ENDIAN_LITTLE) 1191 s.words[1] = bfd_getl32(buffer); 1192 else 1193 s.words[1] = bfd_getb32(buffer); 1194 1195 s._this = &s; 1196 s.coreRegName = _coreRegName; 1197 s.auxRegName = _auxRegName; 1198 s.condCodeName = _condCodeName; 1199 s.instName = _instName; 1200 1201 /* Disassemble. */ 1202 bytes = dsmOneArcInst (address, (void *)& s); 1203 1204 /* Display the disassembly instruction. */ 1205 (*func) (stream, "%08lx ", s.words[0]); 1206 (*func) (stream, " "); 1207 (*func) (stream, "%-10s ", s.instrBuffer); 1208 1209 if (__TRANSLATION_REQUIRED (s)) 1210 { 1211 bfd_vma addr = s.addresses[s.operandBuffer[1] - '0']; 1212 1213 (*info->print_address_func) ((bfd_vma) addr, info); 1214 (*func) (stream, "\n"); 1215 } 1216 else 1217 (*func) (stream, "%s",s.operandBuffer); 1218 1219 return s.instructionLen; 1220 } 1221 1222 /* Return the print_insn function to use. 1223 Side effect: load (possibly empty) extension section */ 1224 1225 disassembler_ftype 1226 arc_get_disassembler (void *ptr) 1227 { 1228 if (ptr) 1229 build_ARC_extmap (ptr); 1230 return decodeInstr; 1231 } 1232