1/* Disassembler code for CR16. 2 Copyright (C) 2007-2022 Free Software Foundation, Inc. 3 Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com). 4 5 This file is part of GAS, GDB and the GNU binutils. 6 7 This program is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published by the 9 Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 This program is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 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 Foundation, 19 Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 20 21#include "sysdep.h" 22#include "disassemble.h" 23#include "opcode/cr16.h" 24#include "libiberty.h" 25 26/* String to print when opcode was not matched. */ 27#define ILLEGAL "illegal" 28 /* Escape to 16-bit immediate. */ 29#define ESCAPE_16_BIT 0xB 30 31/* Extract 'n_bits' from 'a' starting from offset 'offs'. */ 32#define EXTRACT(a, offs, n_bits) \ 33 (((a) >> (offs)) & ((1ul << ((n_bits) - 1) << 1) - 1)) 34 35/* Set Bit Mask - a mask to set all bits in a 32-bit word starting 36 from offset 'offs'. */ 37#define SBM(offs) ((1ul << 31 << 1) - (1ul << (offs))) 38 39/* Structure to map valid 'cinv' instruction options. */ 40 41typedef struct 42 { 43 /* Cinv printed string. */ 44 char *istr; 45 /* Value corresponding to the string. */ 46 char *ostr; 47 } 48cinv_entry; 49 50/* CR16 'cinv' options mapping. */ 51static const cinv_entry cr16_cinvs[] = 52{ 53 {"cinv[i]", "cinv [i]"}, 54 {"cinv[i,u]", "cinv [i,u]"}, 55 {"cinv[d]", "cinv [d]"}, 56 {"cinv[d,u]", "cinv [d,u]"}, 57 {"cinv[d,i]", "cinv [d,i]"}, 58 {"cinv[d,i,u]", "cinv [d,i,u]"} 59}; 60 61/* Number of valid 'cinv' instruction options. */ 62static int NUMCINVS = ARRAY_SIZE (cr16_cinvs); 63 64/* Enum to distinguish different registers argument types. */ 65typedef enum REG_ARG_TYPE 66 { 67 /* General purpose register (r<N>). */ 68 REG_ARG = 0, 69 /*Processor register */ 70 P_ARG, 71 } 72REG_ARG_TYPE; 73 74/* Current opcode table entry we're disassembling. */ 75static const inst *instruction; 76/* Current instruction we're disassembling. */ 77static ins cr16_currInsn; 78/* The current instruction is read into 3 consecutive words. */ 79static wordU cr16_words[3]; 80/* Contains all words in appropriate order. */ 81static ULONGLONG cr16_allWords; 82/* Holds the current processed argument number. */ 83static int processing_argument_number; 84/* Nonzero means a IMM4 instruction. */ 85static int imm4flag; 86/* Nonzero means the instruction's original size is 87 incremented (escape sequence is used). */ 88static int size_changed; 89 90 91/* Print the constant expression length. */ 92 93static char * 94print_exp_len (int size) 95{ 96 switch (size) 97 { 98 case 4: 99 case 5: 100 case 6: 101 case 8: 102 case 14: 103 case 16: 104 return ":s"; 105 case 20: 106 case 24: 107 case 32: 108 return ":m"; 109 case 48: 110 return ":l"; 111 default: 112 return ""; 113 } 114} 115 116 117/* Retrieve the number of operands for the current assembled instruction. */ 118 119static int 120get_number_of_operands (void) 121{ 122 int i; 123 124 for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++) 125 ; 126 127 return i; 128} 129 130/* Return the bit size for a given operand. */ 131 132static int 133getbits (operand_type op) 134{ 135 if (op < MAX_OPRD) 136 return cr16_optab[op].bit_size; 137 138 return 0; 139} 140 141/* Return the argument type of a given operand. */ 142 143static argtype 144getargtype (operand_type op) 145{ 146 if (op < MAX_OPRD) 147 return cr16_optab[op].arg_type; 148 149 return nullargs; 150} 151 152/* Given a 'CC' instruction constant operand, return its corresponding 153 string. This routine is used when disassembling the 'CC' instruction. */ 154 155static char * 156getccstring (unsigned cc_insn) 157{ 158 return (char *) cr16_b_cond_tab[cc_insn]; 159} 160 161 162/* Given a 'cinv' instruction constant operand, return its corresponding 163 string. This routine is used when disassembling the 'cinv' instruction. */ 164 165static char * 166getcinvstring (const char *str) 167{ 168 const cinv_entry *cinv; 169 170 for (cinv = cr16_cinvs; cinv < (cr16_cinvs + NUMCINVS); cinv++) 171 if (strcmp (cinv->istr, str) == 0) 172 return cinv->ostr; 173 174 return ILLEGAL; 175} 176 177/* Given the trap index in dispatch table, return its name. 178 This routine is used when disassembling the 'excp' instruction. */ 179 180static char * 181gettrapstring (unsigned int trap_index) 182{ 183 const trap_entry *trap; 184 185 for (trap = cr16_traps; trap < cr16_traps + NUMTRAPS; trap++) 186 if (trap->entry == trap_index) 187 return trap->name; 188 189 return ILLEGAL; 190} 191 192/* Given a register enum value, retrieve its name. */ 193 194static char * 195getregname (reg r) 196{ 197 const reg_entry * regentry = cr16_regtab + r; 198 199 if (regentry->type != CR16_R_REGTYPE) 200 return ILLEGAL; 201 202 return regentry->name; 203} 204 205/* Given a register pair enum value, retrieve its name. */ 206 207static char * 208getregpname (reg r) 209{ 210 const reg_entry * regentry = cr16_regptab + r; 211 212 if (regentry->type != CR16_RP_REGTYPE) 213 return ILLEGAL; 214 215 return regentry->name; 216} 217 218/* Given a index register pair enum value, retrieve its name. */ 219 220static char * 221getidxregpname (reg r) 222{ 223 const reg_entry * regentry; 224 225 switch (r) 226 { 227 case 0: r = 0; break; 228 case 1: r = 2; break; 229 case 2: r = 4; break; 230 case 3: r = 6; break; 231 case 4: r = 8; break; 232 case 5: r = 10; break; 233 case 6: r = 3; break; 234 case 7: r = 5; break; 235 default: 236 break; 237 } 238 239 regentry = cr16_regptab + r; 240 241 if (regentry->type != CR16_RP_REGTYPE) 242 return ILLEGAL; 243 244 return regentry->name; 245} 246 247/* Getting a processor register name. */ 248 249static char * 250getprocregname (int reg_index) 251{ 252 const reg_entry *r; 253 254 for (r = cr16_pregtab; r < cr16_pregtab + NUMPREGS; r++) 255 if (r->image == reg_index) 256 return r->name; 257 258 return "ILLEGAL REGISTER"; 259} 260 261/* Getting a processor register name - 32 bit size. */ 262 263static char * 264getprocpregname (int reg_index) 265{ 266 const reg_entry *r; 267 268 for (r = cr16_pregptab; r < cr16_pregptab + NUMPREGPS; r++) 269 if (r->image == reg_index) 270 return r->name; 271 272 return "ILLEGAL REGISTER"; 273} 274 275/* START and END are relating 'cr16_allWords' struct, which is 48 bits size. 276 277 START|--------|END 278 +---------+---------+---------+---------+ 279 | | V | A | L | 280 +---------+---------+---------+---------+ 281 0 16 32 48 282 words [0] [1] [2] */ 283 284static inline dwordU 285makelongparameter (ULONGLONG val, int start, int end) 286{ 287 return EXTRACT (val, 48 - end, end - start); 288} 289 290/* Build a mask of the instruction's 'constant' opcode, 291 based on the instruction's printing flags. */ 292 293static unsigned long 294build_mask (void) 295{ 296 unsigned long mask = SBM (instruction->match_bits); 297 298 /* Adjust mask for bcond with 32-bit size instruction. */ 299 if ((IS_INSN_MNEMONIC("b") && instruction->size == 2)) 300 mask = 0xff0f0000; 301 302 return mask; 303} 304 305/* Search for a matching opcode. Return 1 for success, 0 for failure. */ 306 307int 308cr16_match_opcode (void) 309{ 310 unsigned long mask; 311 /* The instruction 'constant' opcode doesn't exceed 32 bits. */ 312 unsigned long doubleWord = cr16_words[1] + ((unsigned) cr16_words[0] << 16); 313 314 /* Start searching from end of instruction table. */ 315 instruction = &cr16_instruction[NUMOPCODES - 2]; 316 317 /* Loop over instruction table until a full match is found. */ 318 while (instruction >= cr16_instruction) 319 { 320 mask = build_mask (); 321 322 if ((doubleWord & mask) == BIN (instruction->match, 323 instruction->match_bits)) 324 return 1; 325 else 326 instruction--; 327 } 328 return 0; 329} 330 331/* Set the proper parameter value for different type of arguments. */ 332 333static void 334make_argument (argument * a, int start_bits) 335{ 336 int inst_bit_size; 337 dwordU p; 338 339 if ((instruction->size == 3) && a->size >= 16) 340 inst_bit_size = 48; 341 else 342 inst_bit_size = 32; 343 344 switch (a->type) 345 { 346 case arg_r: 347 p = makelongparameter (cr16_allWords, 348 inst_bit_size - (start_bits + a->size), 349 inst_bit_size - start_bits); 350 a->r = p; 351 break; 352 353 case arg_rp: 354 p = makelongparameter (cr16_allWords, 355 inst_bit_size - (start_bits + a->size), 356 inst_bit_size - start_bits); 357 a->rp = p; 358 break; 359 360 case arg_pr: 361 p = makelongparameter (cr16_allWords, 362 inst_bit_size - (start_bits + a->size), 363 inst_bit_size - start_bits); 364 a->pr = p; 365 break; 366 367 case arg_prp: 368 p = makelongparameter (cr16_allWords, 369 inst_bit_size - (start_bits + a->size), 370 inst_bit_size - start_bits); 371 a->prp = p; 372 break; 373 374 case arg_ic: 375 p = makelongparameter (cr16_allWords, 376 inst_bit_size - (start_bits + a->size), 377 inst_bit_size - start_bits); 378 a->constant = p; 379 break; 380 381 case arg_cc: 382 p = makelongparameter (cr16_allWords, 383 inst_bit_size - (start_bits + a->size), 384 inst_bit_size - start_bits); 385 a->cc = p; 386 break; 387 388 case arg_idxr: 389 if (IS_INSN_TYPE (CSTBIT_INS) && instruction->mnemonic[4] == 'b') 390 p = makelongparameter (cr16_allWords, 8, 9); 391 else 392 p = makelongparameter (cr16_allWords, 9, 10); 393 a->i_r = p; 394 p = makelongparameter (cr16_allWords, 395 inst_bit_size - a->size, inst_bit_size); 396 a->constant = p; 397 break; 398 399 case arg_idxrp: 400 p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 13); 401 a->i_r = p; 402 p = makelongparameter (cr16_allWords, start_bits + 13, start_bits + 16); 403 a->rp = p; 404 if (inst_bit_size > 32) 405 { 406 p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12, 407 inst_bit_size); 408 a->constant = (p & 0xffff) | (p >> 8 & 0xf0000); 409 } 410 else if (instruction->size == 2) 411 { 412 p = makelongparameter (cr16_allWords, inst_bit_size - 22, 413 inst_bit_size); 414 a->constant = ((p & 0xf) | (((p >> 20) & 0x3) << 4) 415 | ((p >> 14 & 0x3) << 6) | (((p >>7) & 0x1f) << 7)); 416 } 417 else if (instruction->size == 1 && a->size == 0) 418 a->constant = 0; 419 420 break; 421 422 case arg_rbase: 423 p = makelongparameter (cr16_allWords, inst_bit_size, inst_bit_size); 424 a->constant = p; 425 p = makelongparameter (cr16_allWords, inst_bit_size - (start_bits + 4), 426 inst_bit_size - start_bits); 427 a->r = p; 428 break; 429 430 case arg_cr: 431 p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16); 432 a->r = p; 433 p = makelongparameter (cr16_allWords, inst_bit_size - 28, inst_bit_size); 434 a->constant = ((p >> 8) & 0xf0000) | (p & 0xffff); 435 break; 436 437 case arg_crp: 438 if (instruction->size == 1) 439 p = makelongparameter (cr16_allWords, 12, 16); 440 else 441 p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16); 442 a->rp = p; 443 444 if (inst_bit_size > 32) 445 { 446 p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12, 447 inst_bit_size); 448 a->constant = ((p & 0xffff) | (p >> 8 & 0xf0000)); 449 } 450 else if (instruction->size == 2) 451 { 452 p = makelongparameter (cr16_allWords, inst_bit_size - 16, 453 inst_bit_size); 454 a->constant = p; 455 } 456 else if (instruction->size == 1 && a->size != 0) 457 { 458 p = makelongparameter (cr16_allWords, 4, 8); 459 if (IS_INSN_MNEMONIC ("loadw") 460 || IS_INSN_MNEMONIC ("loadd") 461 || IS_INSN_MNEMONIC ("storw") 462 || IS_INSN_MNEMONIC ("stord")) 463 a->constant = p * 2; 464 else 465 a->constant = p; 466 } 467 else /* below case for 0x0(reg pair) */ 468 a->constant = 0; 469 470 break; 471 472 case arg_c: 473 474 if ((IS_INSN_TYPE (BRANCH_INS)) 475 || (IS_INSN_MNEMONIC ("bal")) 476 || (IS_INSN_TYPE (CSTBIT_INS)) 477 || (IS_INSN_TYPE (LD_STOR_INS))) 478 { 479 switch (a->size) 480 { 481 case 8 : 482 p = makelongparameter (cr16_allWords, 0, start_bits); 483 a->constant = ((p & 0xf00) >> 4) | (p & 0xf); 484 break; 485 486 case 24: 487 if (instruction->size == 3) 488 { 489 p = makelongparameter (cr16_allWords, 16, inst_bit_size); 490 a->constant = ((((p >> 16) & 0xf) << 20) 491 | (((p >> 24) & 0xf) << 16) 492 | (p & 0xffff)); 493 } 494 else if (instruction->size == 2) 495 { 496 p = makelongparameter (cr16_allWords, 8, inst_bit_size); 497 a->constant = p; 498 } 499 break; 500 501 default: 502 p = makelongparameter (cr16_allWords, 503 inst_bit_size - (start_bits + a->size), 504 inst_bit_size - start_bits); 505 a->constant = p; 506 break; 507 } 508 } 509 else 510 { 511 p = makelongparameter (cr16_allWords, 512 inst_bit_size - (start_bits + a->size), 513 inst_bit_size - start_bits); 514 a->constant = p; 515 } 516 break; 517 518 default: 519 break; 520 } 521} 522 523/* Print a single argument. */ 524 525static void 526print_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info) 527{ 528 LONGLONG longdisp, mask; 529 int sign_flag = 0; 530 int relative = 0; 531 bfd_vma number; 532 void *stream = info->stream; 533 fprintf_ftype func = info->fprintf_func; 534 535 switch (a->type) 536 { 537 case arg_r: 538 func (stream, "%s", getregname (a->r)); 539 break; 540 541 case arg_rp: 542 func (stream, "%s", getregpname (a->rp)); 543 break; 544 545 case arg_pr: 546 func (stream, "%s", getprocregname (a->pr)); 547 break; 548 549 case arg_prp: 550 func (stream, "%s", getprocpregname (a->prp)); 551 break; 552 553 case arg_cc: 554 func (stream, "%s", getccstring (a->cc)); 555 func (stream, "%s", "\t"); 556 break; 557 558 case arg_ic: 559 if (IS_INSN_MNEMONIC ("excp")) 560 { 561 func (stream, "%s", gettrapstring (a->constant)); 562 break; 563 } 564 else if ((IS_INSN_TYPE (ARITH_INS) || IS_INSN_TYPE (ARITH_BYTE_INS)) 565 && ((instruction->size == 1) && (a->constant == 9))) 566 func (stream, "$%d", -1); 567 else if (INST_HAS_REG_LIST) 568 func (stream, "$0x%lx", a->constant +1); 569 else if (IS_INSN_TYPE (SHIFT_INS)) 570 { 571 longdisp = a->constant; 572 mask = ((LONGLONG)1 << a->size) - 1; 573 if (longdisp & ((LONGLONG)1 << (a->size -1))) 574 { 575 sign_flag = 1; 576 longdisp = ~(longdisp) + 1; 577 } 578 a->constant = (unsigned long int) (longdisp & mask); 579 func (stream, "$%d", ((int)(sign_flag ? -a->constant : 580 a->constant))); 581 } 582 else 583 func (stream, "$0x%lx", a->constant); 584 switch (a->size) 585 { 586 case 4 : case 5 : case 6 : case 8 : 587 func (stream, "%s", ":s"); break; 588 case 16 : case 20 : func (stream, "%s", ":m"); break; 589 case 24 : case 32 : func (stream, "%s", ":l"); break; 590 default: break; 591 } 592 break; 593 594 case arg_idxr: 595 if (a->i_r == 0) func (stream, "[r12]"); 596 if (a->i_r == 1) func (stream, "[r13]"); 597 func (stream, "0x%lx", a->constant); 598 func (stream, "%s", print_exp_len (instruction->size * 16)); 599 break; 600 601 case arg_idxrp: 602 if (a->i_r == 0) func (stream, "[r12]"); 603 if (a->i_r == 1) func (stream, "[r13]"); 604 func (stream, "0x%lx", a->constant); 605 func (stream, "%s", print_exp_len (instruction->size * 16)); 606 func (stream, "%s", getidxregpname (a->rp)); 607 break; 608 609 case arg_rbase: 610 func (stream, "(%s)", getregname (a->r)); 611 break; 612 613 case arg_cr: 614 func (stream, "0x%lx", a->constant); 615 func (stream, "%s", print_exp_len (instruction->size * 16)); 616 func (stream, "(%s)", getregname (a->r)); 617 break; 618 619 case arg_crp: 620 func (stream, "0x%lx", a->constant); 621 func (stream, "%s", print_exp_len (instruction->size * 16)); 622 func (stream, "%s", getregpname (a->rp)); 623 break; 624 625 case arg_c: 626 /*Removed the *2 part as because implicit zeros are no more required. 627 Have to fix this as this needs a bit of extension in terms of branch 628 instructions. */ 629 if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal")) 630 { 631 relative = 1; 632 longdisp = a->constant; 633 /* REVISIT: To sync with WinIDEA and CR16 4.1tools, the below 634 line commented */ 635 /* longdisp <<= 1; */ 636 mask = ((LONGLONG)1 << a->size) - 1; 637 switch (a->size) 638 { 639 case 8 : 640 { 641 longdisp <<= 1; 642 if (longdisp & ((LONGLONG)1 << a->size)) 643 { 644 sign_flag = 1; 645 longdisp = ~(longdisp) + 1; 646 } 647 break; 648 } 649 case 16 : 650 case 24 : 651 { 652 if (longdisp & 1) 653 { 654 sign_flag = 1; 655 longdisp = ~(longdisp) + 1; 656 } 657 break; 658 } 659 default: 660 func (stream, "Wrong offset used in branch/bal instruction"); 661 break; 662 } 663 a->constant = (unsigned long int) (longdisp & mask); 664 } 665 /* For branch Neq instruction it is 2*offset + 2. */ 666 else if (IS_INSN_TYPE (BRANCH_NEQ_INS)) 667 a->constant = 2 * a->constant + 2; 668 669 if ((!IS_INSN_TYPE (CSTBIT_INS)) && (!IS_INSN_TYPE (LD_STOR_INS))) 670 (sign_flag) ? func (stream, "%s", "*-"): func (stream, "%s","*+"); 671 672 /* PR 10173: Avoid printing the 0x prefix twice. */ 673 if (info->symtab_size > 0) 674 func (stream, "%s", "0x"); 675 number = ((relative ? memaddr : 0) + 676 (sign_flag ? ((- a->constant) & 0xffffffe) : a->constant)); 677 678 (*info->print_address_func) ((number & ((1 << 24) - 1)), info); 679 680 func (stream, "%s", print_exp_len (instruction->size * 16)); 681 break; 682 683 default: 684 break; 685 } 686} 687 688/* Print all the arguments of CURRINSN instruction. */ 689 690static void 691print_arguments (ins *currentInsn, bfd_vma memaddr, struct disassemble_info *info) 692{ 693 int i; 694 695 /* For "pop/push/popret RA instruction only. */ 696 if ((IS_INSN_MNEMONIC ("pop") 697 || (IS_INSN_MNEMONIC ("popret") 698 || (IS_INSN_MNEMONIC ("push")))) 699 && currentInsn->nargs == 1) 700 { 701 info->fprintf_func (info->stream, "RA"); 702 return; 703 } 704 705 for (i = 0; i < currentInsn->nargs; i++) 706 { 707 processing_argument_number = i; 708 709 /* For "bal (ra), disp17" instruction only. */ 710 if ((IS_INSN_MNEMONIC ("bal")) && (i == 0) && instruction->size == 2) 711 { 712 info->fprintf_func (info->stream, "(ra),"); 713 continue; 714 } 715 716 if ((INST_HAS_REG_LIST) && (i == 2)) 717 info->fprintf_func (info->stream, "RA"); 718 else 719 print_arg (¤tInsn->arg[i], memaddr, info); 720 721 if ((i != currentInsn->nargs - 1) && (!IS_INSN_MNEMONIC ("b"))) 722 info->fprintf_func (info->stream, ","); 723 } 724} 725 726/* Build the instruction's arguments. */ 727 728void 729cr16_make_instruction (void) 730{ 731 int i; 732 unsigned int shift; 733 734 for (i = 0; i < cr16_currInsn.nargs; i++) 735 { 736 argument a; 737 738 memset (&a, 0, sizeof (a)); 739 a.type = getargtype (instruction->operands[i].op_type); 740 a.size = getbits (instruction->operands[i].op_type); 741 shift = instruction->operands[i].shift; 742 743 make_argument (&a, shift); 744 cr16_currInsn.arg[i] = a; 745 } 746 747 /* Calculate instruction size (in bytes). */ 748 cr16_currInsn.size = instruction->size + (size_changed ? 1 : 0); 749 /* Now in bits. */ 750 cr16_currInsn.size *= 2; 751} 752 753/* Retrieve a single word from a given memory address. */ 754 755static wordU 756get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info) 757{ 758 bfd_byte buffer[4]; 759 int status; 760 wordU insn = 0; 761 762 status = info->read_memory_func (memaddr, buffer, 2, info); 763 764 if (status == 0) 765 insn = (wordU) bfd_getl16 (buffer); 766 767 return insn; 768} 769 770/* Retrieve multiple words (3) from a given memory address. */ 771 772static void 773get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info) 774{ 775 int i; 776 bfd_vma mem; 777 778 for (i = 0, mem = memaddr; i < 3; i++, mem += 2) 779 cr16_words[i] = get_word_at_PC (mem, info); 780 781 cr16_allWords = ((ULONGLONG) cr16_words[0] << 32) 782 + ((unsigned long) cr16_words[1] << 16) + cr16_words[2]; 783} 784 785/* Prints the instruction by calling print_arguments after proper matching. */ 786 787int 788print_insn_cr16 (bfd_vma memaddr, struct disassemble_info *info) 789{ 790 int is_decoded; /* Nonzero means instruction has a match. */ 791 792 /* Initialize global variables. */ 793 imm4flag = 0; 794 size_changed = 0; 795 796 /* Retrieve the encoding from current memory location. */ 797 get_words_at_PC (memaddr, info); 798 /* Find a matching opcode in table. */ 799 is_decoded = cr16_match_opcode (); 800 /* If found, print the instruction's mnemonic and arguments. */ 801 if (is_decoded > 0 && (cr16_words[0] != 0 || cr16_words[1] != 0)) 802 { 803 if (startswith (instruction->mnemonic, "cinv")) 804 info->fprintf_func (info->stream,"%s", 805 getcinvstring (instruction->mnemonic)); 806 else 807 info->fprintf_func (info->stream, "%s", instruction->mnemonic); 808 809 if (((cr16_currInsn.nargs = get_number_of_operands ()) != 0) 810 && ! (IS_INSN_MNEMONIC ("b"))) 811 info->fprintf_func (info->stream, "\t"); 812 cr16_make_instruction (); 813 /* For push/pop/pushrtn with RA instructions. */ 814 if ((INST_HAS_REG_LIST) && ((cr16_words[0] >> 7) & 0x1)) 815 cr16_currInsn.nargs +=1; 816 print_arguments (&cr16_currInsn, memaddr, info); 817 return cr16_currInsn.size; 818 } 819 820 /* No match found. */ 821 info->fprintf_func (info->stream,"%s ",ILLEGAL); 822 return 2; 823} 824