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