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