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