Home | History | Annotate | Download | only in opcodes
      1 /* Disassembler code for CRX.
      2    Copyright (C) 2004-2016 Free Software Foundation, Inc.
      3    Contributed by Tomer Levi, NSC, Israel.
      4    Written by Tomer Levi.
      5 
      6    This file is part of the GNU opcodes library.
      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 "sysdep.h"
     24 #include "dis-asm.h"
     25 #include "opcode/crx.h"
     26 
     27 /* String to print when opcode was not matched.  */
     28 #define ILLEGAL	"illegal"
     29   /* Escape to 16-bit immediate.  */
     30 #define ESCAPE_16_BIT  0xE
     31 
     32 /* Extract 'n_bits' from 'a' starting from offset 'offs'.  */
     33 #define EXTRACT(a, offs, n_bits)	    \
     34   (n_bits == 32 ? (((a) >> (offs)) & 0xffffffffL)   \
     35   : (((a) >> (offs)) & ((1 << (n_bits)) -1)))
     36 
     37 /* Set Bit Mask - a mask to set all bits starting from offset 'offs'.  */
     38 #define SBM(offs)  ((((1 << (32 - offs)) -1) << (offs)))
     39 
     40 typedef unsigned long dwordU;
     41 typedef unsigned short wordU;
     42 
     43 typedef struct
     44 {
     45   dwordU val;
     46   int nbits;
     47 } parameter;
     48 
     49 /* Structure to hold valid 'cinv' instruction options.  */
     50 
     51 typedef struct
     52   {
     53     /* Cinv printed string.  */
     54     char *str;
     55     /* Value corresponding to the string.  */
     56     unsigned int value;
     57   }
     58 cinv_entry;
     59 
     60 /* CRX 'cinv' options.  */
     61 const cinv_entry crx_cinvs[] =
     62 {
     63   {"[i]", 2}, {"[i,u]", 3}, {"[d]", 4}, {"[d,u]", 5},
     64   {"[d,i]", 6}, {"[d,i,u]", 7}, {"[b]", 8},
     65   {"[b,i]", 10}, {"[b,i,u]", 11}, {"[b,d]", 12},
     66   {"[b,d,u]", 13}, {"[b,d,i]", 14}, {"[b,d,i,u]", 15}
     67 };
     68 
     69 /* Enum to distinguish different registers argument types.  */
     70 typedef enum REG_ARG_TYPE
     71   {
     72     /* General purpose register (r<N>).  */
     73     REG_ARG = 0,
     74     /* User register (u<N>).  */
     75     USER_REG_ARG,
     76     /* CO-Processor register (c<N>).  */
     77     COP_ARG,
     78     /* CO-Processor special register (cs<N>).  */
     79     COPS_ARG
     80   }
     81 REG_ARG_TYPE;
     82 
     83 /* Number of valid 'cinv' instruction options.  */
     84 int NUMCINVS = ((sizeof crx_cinvs)/(sizeof crx_cinvs[0]));
     85 /* Current opcode table entry we're disassembling.  */
     86 const inst *instruction;
     87 /* Current instruction we're disassembling.  */
     88 ins currInsn;
     89 /* The current instruction is read into 3 consecutive words.  */
     90 wordU words[3];
     91 /* Contains all words in appropriate order.  */
     92 ULONGLONG allWords;
     93 /* Holds the current processed argument number.  */
     94 int processing_argument_number;
     95 /* Nonzero means a CST4 instruction.  */
     96 int cst4flag;
     97 /* Nonzero means the instruction's original size is
     98    incremented (escape sequence is used).  */
     99 int size_changed;
    100 
    101 static int get_number_of_operands (void);
    102 static argtype getargtype     (operand_type);
    103 static int getbits	      (operand_type);
    104 static char *getregname	      (reg);
    105 static char *getcopregname    (copreg, reg_type);
    106 static char * getprocregname  (int);
    107 static char *gettrapstring    (unsigned);
    108 static char *getcinvstring    (unsigned);
    109 static void getregliststring  (int, char *, enum REG_ARG_TYPE);
    110 static wordU get_word_at_PC   (bfd_vma, struct disassemble_info *);
    111 static void get_words_at_PC   (bfd_vma, struct disassemble_info *);
    112 static unsigned long build_mask (void);
    113 static int powerof2	      (int);
    114 static int match_opcode	      (void);
    115 static void make_instruction  (void);
    116 static void print_arguments   (ins *, bfd_vma, struct disassemble_info *);
    117 static void print_arg	      (argument *, bfd_vma, struct disassemble_info *);
    118 
    119 /* Retrieve the number of operands for the current assembled instruction.  */
    120 
    121 static int
    122 get_number_of_operands (void)
    123 {
    124   int i;
    125 
    126   for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
    127     ;
    128 
    129   return i;
    130 }
    131 
    132 /* Return the bit size for a given operand.  */
    133 
    134 static int
    135 getbits (operand_type op)
    136 {
    137   if (op < MAX_OPRD)
    138     return crx_optab[op].bit_size;
    139   else
    140     return 0;
    141 }
    142 
    143 /* Return the argument type of a given operand.  */
    144 
    145 static argtype
    146 getargtype (operand_type op)
    147 {
    148   if (op < MAX_OPRD)
    149     return crx_optab[op].arg_type;
    150   else
    151     return nullargs;
    152 }
    153 
    154 /* Given the trap index in dispatch table, return its name.
    155    This routine is used when disassembling the 'excp' instruction.  */
    156 
    157 static char *
    158 gettrapstring (unsigned int trap_index)
    159 {
    160   const trap_entry *trap;
    161 
    162   for (trap = crx_traps; trap < crx_traps + NUMTRAPS; trap++)
    163     if (trap->entry == trap_index)
    164       return trap->name;
    165 
    166   return ILLEGAL;
    167 }
    168 
    169 /* Given a 'cinv' instruction constant operand, return its corresponding string.
    170    This routine is used when disassembling the 'cinv' instruction.  */
    171 
    172 static char *
    173 getcinvstring (unsigned int num)
    174 {
    175   const cinv_entry *cinv;
    176 
    177   for (cinv = crx_cinvs; cinv < (crx_cinvs + NUMCINVS); cinv++)
    178     if (cinv->value == num)
    179       return cinv->str;
    180 
    181   return ILLEGAL;
    182 }
    183 
    184 /* Given a register enum value, retrieve its name.  */
    185 
    186 char *
    187 getregname (reg r)
    188 {
    189   const reg_entry * regentry = &crx_regtab[r];
    190 
    191   if (regentry->type != CRX_R_REGTYPE)
    192     return ILLEGAL;
    193   else
    194     return regentry->name;
    195 }
    196 
    197 /* Given a coprocessor register enum value, retrieve its name.  */
    198 
    199 char *
    200 getcopregname (copreg r, reg_type type)
    201 {
    202   const reg_entry * regentry;
    203 
    204   if (type == CRX_C_REGTYPE)
    205     regentry = &crx_copregtab[r];
    206   else if (type == CRX_CS_REGTYPE)
    207     regentry = &crx_copregtab[r+(cs0-c0)];
    208   else
    209     return ILLEGAL;
    210 
    211   return regentry->name;
    212 }
    213 
    214 
    215 /* Getting a processor register name.  */
    216 
    217 static char *
    218 getprocregname (int reg_index)
    219 {
    220   const reg_entry *r;
    221 
    222   for (r = crx_regtab; r < crx_regtab + NUMREGS; r++)
    223     if (r->image == reg_index)
    224       return r->name;
    225 
    226   return "ILLEGAL REGISTER";
    227 }
    228 
    229 /* Get the power of two for a given integer.  */
    230 
    231 static int
    232 powerof2 (int x)
    233 {
    234   int product, i;
    235 
    236   for (i = 0, product = 1; i < x; i++)
    237     product *= 2;
    238 
    239   return product;
    240 }
    241 
    242 /* Transform a register bit mask to a register list.  */
    243 
    244 void
    245 getregliststring (int mask, char *string, enum REG_ARG_TYPE core_cop)
    246 {
    247   char temp_string[5];
    248   int i;
    249 
    250   string[0] = '{';
    251   string[1] = '\0';
    252 
    253 
    254   /* A zero mask means HI/LO registers.  */
    255   if (mask == 0)
    256     {
    257       if (core_cop == USER_REG_ARG)
    258 	strcat (string, "ulo,uhi");
    259       else
    260 	strcat (string, "lo,hi");
    261     }
    262   else
    263     {
    264       for (i = 0; i < 16; i++)
    265 	{
    266 	  if (mask & 0x1)
    267 	    {
    268 	      switch (core_cop)
    269 	      {
    270 	      case REG_ARG:
    271 		sprintf (temp_string, "r%d", i);
    272 		break;
    273 	      case USER_REG_ARG:
    274 		sprintf (temp_string, "u%d", i);
    275 		break;
    276 	      case COP_ARG:
    277 		sprintf (temp_string, "c%d", i);
    278 		break;
    279 	      case COPS_ARG:
    280 		sprintf (temp_string, "cs%d", i);
    281 		break;
    282 	      default:
    283 		break;
    284 	      }
    285 	      strcat (string, temp_string);
    286 	      if (mask & 0xfffe)
    287 		strcat (string, ",");
    288 	    }
    289 	  mask >>= 1;
    290 	}
    291     }
    292 
    293   strcat (string, "}");
    294 }
    295 
    296 /* START and END are relating 'allWords' struct, which is 48 bits size.
    297 
    298 			  START|--------|END
    299 	    +---------+---------+---------+---------+
    300 	    |	      |	   V    |     A	  |   L	    |
    301 	    +---------+---------+---------+---------+
    302 	    	      0		16	  32	    48
    303     words		  [0]	    [1]	      [2]	*/
    304 
    305 static parameter
    306 makelongparameter (ULONGLONG val, int start, int end)
    307 {
    308   parameter p;
    309 
    310   p.val = (dwordU) EXTRACT(val, 48 - end, end - start);
    311   p.nbits = end - start;
    312   return p;
    313 }
    314 
    315 /* Build a mask of the instruction's 'constant' opcode,
    316    based on the instruction's printing flags.  */
    317 
    318 static unsigned long
    319 build_mask (void)
    320 {
    321   unsigned int print_flags;
    322   unsigned long mask;
    323 
    324   print_flags = instruction->flags & FMT_CRX;
    325   switch (print_flags)
    326     {
    327       case FMT_1:
    328 	mask = 0xF0F00000;
    329 	break;
    330       case FMT_2:
    331 	mask = 0xFFF0FF00;
    332 	break;
    333       case FMT_3:
    334 	mask = 0xFFF00F00;
    335 	break;
    336       case FMT_4:
    337 	mask = 0xFFF0F000;
    338 	break;
    339       case FMT_5:
    340 	mask = 0xFFF0FFF0;
    341 	break;
    342       default:
    343 	mask = SBM(instruction->match_bits);
    344 	break;
    345     }
    346 
    347   return mask;
    348 }
    349 
    350 /* Search for a matching opcode. Return 1 for success, 0 for failure.  */
    351 
    352 static int
    353 match_opcode (void)
    354 {
    355   unsigned long mask;
    356 
    357   /* The instruction 'constant' opcode doewsn't exceed 32 bits.  */
    358   unsigned long doubleWord = (words[1] + (words[0] << 16)) & 0xffffffff;
    359 
    360   /* Start searching from end of instruction table.  */
    361   instruction = &crx_instruction[NUMOPCODES - 2];
    362 
    363   /* Loop over instruction table until a full match is found.  */
    364   while (instruction >= crx_instruction)
    365     {
    366       mask = build_mask ();
    367       if ((doubleWord & mask) == BIN(instruction->match, instruction->match_bits))
    368 	return 1;
    369       else
    370 	instruction--;
    371     }
    372   return 0;
    373 }
    374 
    375 /* Set the proper parameter value for different type of arguments.  */
    376 
    377 static void
    378 make_argument (argument * a, int start_bits)
    379 {
    380   int inst_bit_size, total_size;
    381   parameter p;
    382 
    383   if ((instruction->size == 3) && a->size >= 16)
    384     inst_bit_size = 48;
    385   else
    386     inst_bit_size = 32;
    387 
    388   switch (a->type)
    389     {
    390     case arg_copr:
    391     case arg_copsr:
    392       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
    393 			     inst_bit_size - start_bits);
    394       a->cr = p.val;
    395       break;
    396 
    397     case arg_r:
    398       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
    399 			     inst_bit_size - start_bits);
    400       a->r = p.val;
    401       break;
    402 
    403     case arg_ic:
    404       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
    405 			     inst_bit_size - start_bits);
    406 
    407       if ((p.nbits == 4) && cst4flag)
    408         {
    409 	  if (IS_INSN_TYPE (CMPBR_INS) && (p.val == ESCAPE_16_BIT))
    410 	    {
    411 	      /* A special case, where the value is actually stored
    412 		 in the last 4 bits.  */
    413 	      p = makelongparameter (allWords, 44, 48);
    414 	      /* The size of the instruction should be incremented.  */
    415 	      size_changed = 1;
    416 	    }
    417 
    418           if (p.val == 6)
    419             p.val = -1;
    420           else if (p.val == 13)
    421             p.val = 48;
    422           else if (p.val == 5)
    423             p.val = -4;
    424           else if (p.val == 10)
    425             p.val = 32;
    426           else if (p.val == 11)
    427             p.val = 20;
    428           else if (p.val == 9)
    429             p.val = 16;
    430         }
    431 
    432       a->constant = p.val;
    433       break;
    434 
    435     case arg_idxr:
    436       a->scale = 0;
    437       total_size = a->size + 10;  /* sizeof(rbase + ridx + scl2) = 10.  */
    438       p = makelongparameter (allWords, inst_bit_size - total_size,
    439 			     inst_bit_size - (total_size - 4));
    440       a->r = p.val;
    441       p = makelongparameter (allWords, inst_bit_size - (total_size - 4),
    442 			     inst_bit_size - (total_size - 8));
    443       a->i_r = p.val;
    444       p = makelongparameter (allWords, inst_bit_size - (total_size - 8),
    445 			     inst_bit_size - (total_size - 10));
    446       a->scale = p.val;
    447       p = makelongparameter (allWords, inst_bit_size - (total_size - 10),
    448 			     inst_bit_size);
    449       a->constant = p.val;
    450       break;
    451 
    452     case arg_rbase:
    453       p = makelongparameter (allWords, inst_bit_size - (start_bits + 4),
    454 			     inst_bit_size - start_bits);
    455       a->r = p.val;
    456       break;
    457 
    458     case arg_cr:
    459       if (a->size <= 8)
    460         {
    461           p = makelongparameter (allWords, inst_bit_size - (start_bits + 4),
    462 				 inst_bit_size - start_bits);
    463           a->r = p.val;
    464           /* Case for opc4 r dispu rbase.  */
    465           p = makelongparameter (allWords, inst_bit_size - (start_bits + 8),
    466 				 inst_bit_size - (start_bits + 4));
    467         }
    468       else
    469         {
    470 	  /* The 'rbase' start_bits is always relative to a 32-bit data type.  */
    471           p = makelongparameter (allWords, 32 - (start_bits + 4),
    472 				 32 - start_bits);
    473           a->r = p.val;
    474           p = makelongparameter (allWords, 32 - start_bits,
    475 				 inst_bit_size);
    476         }
    477       if ((p.nbits == 4) && cst4flag)
    478         {
    479           if (instruction->flags & DISPUW4)
    480 	    p.val *= 2;
    481           else if (instruction->flags & DISPUD4)
    482 	    p.val *= 4;
    483         }
    484       a->constant = p.val;
    485       break;
    486 
    487     case arg_c:
    488       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
    489 			     inst_bit_size - start_bits);
    490       a->constant = p.val;
    491       break;
    492     default:
    493       break;
    494     }
    495 }
    496 
    497 /*  Print a single argument.  */
    498 
    499 static void
    500 print_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info)
    501 {
    502   LONGLONG longdisp, mask;
    503   int sign_flag = 0;
    504   int relative = 0;
    505   bfd_vma number;
    506   int op_index = 0;
    507   char string[200];
    508   PTR stream = info->stream;
    509   fprintf_ftype func = info->fprintf_func;
    510 
    511   switch (a->type)
    512     {
    513     case arg_copr:
    514       func (stream, "%s", getcopregname (a->cr, CRX_C_REGTYPE));
    515       break;
    516 
    517     case arg_copsr:
    518       func (stream, "%s", getcopregname (a->cr, CRX_CS_REGTYPE));
    519       break;
    520 
    521     case arg_r:
    522       if (IS_INSN_MNEMONIC ("mtpr") || IS_INSN_MNEMONIC ("mfpr"))
    523 	func (stream, "%s", getprocregname (a->r));
    524       else
    525 	func (stream, "%s", getregname (a->r));
    526       break;
    527 
    528     case arg_ic:
    529       if (IS_INSN_MNEMONIC ("excp"))
    530 	func (stream, "%s", gettrapstring (a->constant));
    531 
    532       else if (IS_INSN_MNEMONIC ("cinv"))
    533 	func (stream, "%s", getcinvstring (a->constant));
    534 
    535       else if (INST_HAS_REG_LIST)
    536         {
    537 	  REG_ARG_TYPE reg_arg_type = IS_INSN_TYPE (COP_REG_INS) ?
    538 				 COP_ARG : IS_INSN_TYPE (COPS_REG_INS) ?
    539 				 COPS_ARG : (instruction->flags & USER_REG) ?
    540 				 USER_REG_ARG : REG_ARG;
    541 
    542           if ((reg_arg_type == COP_ARG) || (reg_arg_type == COPS_ARG))
    543 	    {
    544 		/*  Check for proper argument number.  */
    545 		if (processing_argument_number == 2)
    546 		  {
    547 		    getregliststring (a->constant, string, reg_arg_type);
    548 		    func (stream, "%s", string);
    549 		  }
    550 		else
    551 		  func (stream, "$0x%lx", a->constant & 0xffffffff);
    552 	    }
    553 	  else
    554             {
    555               getregliststring (a->constant, string, reg_arg_type);
    556               func (stream, "%s", string);
    557             }
    558         }
    559       else
    560 	func (stream, "$0x%lx", a->constant & 0xffffffff);
    561       break;
    562 
    563     case arg_idxr:
    564       func (stream, "0x%lx(%s,%s,%d)", a->constant & 0xffffffff,
    565 	    getregname (a->r), getregname (a->i_r), powerof2 (a->scale));
    566       break;
    567 
    568     case arg_rbase:
    569       func (stream, "(%s)", getregname (a->r));
    570       break;
    571 
    572     case arg_cr:
    573       func (stream, "0x%lx(%s)", a->constant & 0xffffffff, getregname (a->r));
    574 
    575       if (IS_INSN_TYPE (LD_STOR_INS_INC))
    576 	func (stream, "+");
    577       break;
    578 
    579     case arg_c:
    580       /* Removed the *2 part as because implicit zeros are no more required.
    581 	 Have to fix this as this needs a bit of extension in terms of branchins.
    582 	 Have to add support for cmp and branch instructions.  */
    583       if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal")
    584 	  || IS_INSN_TYPE (CMPBR_INS) || IS_INSN_TYPE (DCR_BRANCH_INS)
    585 	  || IS_INSN_TYPE (COP_BRANCH_INS))
    586         {
    587 	  relative = 1;
    588           longdisp = a->constant;
    589           longdisp <<= 1;
    590 
    591           switch (a->size)
    592             {
    593             case 8:
    594 	    case 16:
    595 	    case 24:
    596 	    case 32:
    597 	      mask = ((LONGLONG)1 << a->size) - 1;
    598               if (longdisp & ((LONGLONG)1 << a->size))
    599                 {
    600                   sign_flag = 1;
    601                   longdisp = ~(longdisp) + 1;
    602                 }
    603               a->constant = (unsigned long int) (longdisp & mask);
    604               break;
    605             default:
    606 	      func (stream,
    607 		    "Wrong offset used in branch/bal instruction");
    608               break;
    609             }
    610 
    611         }
    612       /* For branch Neq instruction it is 2*offset + 2.  */
    613       else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
    614 	a->constant = 2 * a->constant + 2;
    615       else if (IS_INSN_TYPE (LD_STOR_INS_INC)
    616 	  || IS_INSN_TYPE (LD_STOR_INS)
    617 	  || IS_INSN_TYPE (STOR_IMM_INS)
    618 	  || IS_INSN_TYPE (CSTBIT_INS))
    619         {
    620           op_index = instruction->flags & REVERSE_MATCH ? 0 : 1;
    621           if (instruction->operands[op_index].op_type == abs16)
    622 	    a->constant |= 0xFFFF0000;
    623         }
    624       func (stream, "%s", "0x");
    625       number = (relative ? memaddr : 0)
    626 	       + (sign_flag ? -a->constant : a->constant);
    627       (*info->print_address_func) (number, info);
    628       break;
    629     default:
    630       break;
    631     }
    632 }
    633 
    634 /* Print all the arguments of CURRINSN instruction.  */
    635 
    636 static void
    637 print_arguments (ins *currentInsn, bfd_vma memaddr, struct disassemble_info *info)
    638 {
    639   int i;
    640 
    641   for (i = 0; i < currentInsn->nargs; i++)
    642     {
    643       processing_argument_number = i;
    644 
    645       print_arg (&currentInsn->arg[i], memaddr, info);
    646 
    647       if (i != currentInsn->nargs - 1)
    648 	info->fprintf_func (info->stream, ", ");
    649     }
    650 }
    651 
    652 /* Build the instruction's arguments.  */
    653 
    654 static void
    655 make_instruction (void)
    656 {
    657   int i;
    658   unsigned int shift;
    659 
    660   for (i = 0; i < currInsn.nargs; i++)
    661     {
    662       argument a;
    663 
    664       memset (&a, 0, sizeof (a));
    665       a.type = getargtype (instruction->operands[i].op_type);
    666       if (instruction->operands[i].op_type == cst4
    667 	  || instruction->operands[i].op_type == rbase_dispu4)
    668 	cst4flag = 1;
    669       a.size = getbits (instruction->operands[i].op_type);
    670       shift = instruction->operands[i].shift;
    671 
    672       make_argument (&a, shift);
    673       currInsn.arg[i] = a;
    674     }
    675 
    676   /* Calculate instruction size (in bytes).  */
    677   currInsn.size = instruction->size + (size_changed ? 1 : 0);
    678   /* Now in bits.  */
    679   currInsn.size *= 2;
    680 }
    681 
    682 /* Retrieve a single word from a given memory address.  */
    683 
    684 static wordU
    685 get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info)
    686 {
    687   bfd_byte buffer[4];
    688   int status;
    689   wordU insn = 0;
    690 
    691   status = info->read_memory_func (memaddr, buffer, 2, info);
    692 
    693   if (status == 0)
    694     insn = (wordU) bfd_getl16 (buffer);
    695 
    696   return insn;
    697 }
    698 
    699 /* Retrieve multiple words (3) from a given memory address.  */
    700 
    701 static void
    702 get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info)
    703 {
    704   int i;
    705   bfd_vma mem;
    706 
    707   for (i = 0, mem = memaddr; i < 3; i++, mem += 2)
    708     words[i] = get_word_at_PC (mem, info);
    709 
    710   allWords =
    711     ((ULONGLONG) words[0] << 32) + ((unsigned long) words[1] << 16) + words[2];
    712 }
    713 
    714 /* Prints the instruction by calling print_arguments after proper matching.  */
    715 
    716 int
    717 print_insn_crx (bfd_vma memaddr, struct disassemble_info *info)
    718 {
    719   int is_decoded;     /* Nonzero means instruction has a match.  */
    720 
    721   /* Initialize global variables.  */
    722   cst4flag = 0;
    723   size_changed = 0;
    724 
    725   /* Retrieve the encoding from current memory location.  */
    726   get_words_at_PC (memaddr, info);
    727   /* Find a matching opcode in table.  */
    728   is_decoded = match_opcode ();
    729   /* If found, print the instruction's mnemonic and arguments.  */
    730   if (is_decoded > 0 && (words[0] << 16 || words[1]) != 0)
    731     {
    732       info->fprintf_func (info->stream, "%s", instruction->mnemonic);
    733       if ((currInsn.nargs = get_number_of_operands ()) != 0)
    734 	info->fprintf_func (info->stream, "\t");
    735       make_instruction ();
    736       print_arguments (&currInsn, memaddr, info);
    737       return currInsn.size;
    738     }
    739 
    740   /* No match found.  */
    741   info->fprintf_func (info->stream,"%s ",ILLEGAL);
    742   return 2;
    743 }
    744