1/* Disassembler code for CR16.
2   Copyright 2007 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 under
8   the terms of the GNU General Public License as published by the Free
9   Software Foundation; either version 2, 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 "dis-asm.h"
22#include "sysdep.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  (n_bits == 32 ? (((a) >> (offs)) & 0xffffffffL)   \
34  : (((a) >> (offs)) & ((1 << (n_bits)) -1)))
35
36/* Set Bit Mask - a mask to set all bits starting from offset 'offs'.  */
37#define SBM(offs)  ((((1 << (32 - offs)) -1) << (offs)))
38
39typedef unsigned long dwordU;
40typedef unsigned short wordU;
41
42typedef struct
43{
44  dwordU val;
45  int nbits;
46} parameter;
47
48/* Structure to map valid 'cinv' instruction options.  */
49
50typedef struct
51  {
52    /* Cinv printed string.  */
53    char *istr;
54    /* Value corresponding to the string.  */
55    char *ostr;
56  }
57cinv_entry;
58
59/* CR16 'cinv' options mapping.  */
60const cinv_entry cr16_cinvs[] =
61{
62  {"cinv[i]",     "cinv    [i]"},
63  {"cinv[i,u]",   "cinv    [i,u]"},
64  {"cinv[d]",     "cinv    [d]"},
65  {"cinv[d,u]",   "cinv    [d,u]"},
66  {"cinv[d,i]",   "cinv    [d,i]"},
67  {"cinv[d,i,u]", "cinv    [d,i,u]"}
68};
69
70/* Number of valid 'cinv' instruction options.  */
71static int NUMCINVS = ARRAY_SIZE (cr16_cinvs);
72
73/* Enum to distinguish different registers argument types.  */
74typedef enum REG_ARG_TYPE
75  {
76    /* General purpose register (r<N>).  */
77    REG_ARG = 0,
78    /*Processor register   */
79    P_ARG,
80  }
81REG_ARG_TYPE;
82
83/* Current opcode table entry we're disassembling.  */
84const inst *instruction;
85/* Current instruction we're disassembling.  */
86ins currInsn;
87/* The current instruction is read into 3 consecutive words.  */
88wordU words[3];
89/* Contains all words in appropriate order.  */
90ULONGLONG allWords;
91/* Holds the current processed argument number.  */
92int processing_argument_number;
93/* Nonzero means a IMM4 instruction.  */
94int imm4flag;
95/* Nonzero means the instruction's original size is
96   incremented (escape sequence is used).  */
97int size_changed;
98
99
100/* Print the constant expression length.  */
101
102static char *
103print_exp_len (int size)
104{
105  switch (size)
106    {
107    case 4:
108    case 5:
109    case 6:
110    case 8:
111    case 14:
112    case 16:
113      return ":s";
114    case 20:
115    case 24:
116    case 32:
117      return ":m";
118    case 48:
119      return ":l";
120    default:
121      return "";
122    }
123}
124
125
126/* Retrieve the number of operands for the current assembled instruction.  */
127
128static int
129get_number_of_operands (void)
130{
131  int i;
132
133  for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
134    ;
135
136  return i;
137}
138
139/* Return the bit size for a given operand.  */
140
141static int
142getbits (operand_type op)
143{
144  if (op < MAX_OPRD)
145    return cr16_optab[op].bit_size;
146
147  return 0;
148}
149
150/* Return the argument type of a given operand.  */
151
152static argtype
153getargtype (operand_type op)
154{
155  if (op < MAX_OPRD)
156    return cr16_optab[op].arg_type;
157
158  return nullargs;
159}
160
161/* Given a 'CC' instruction constant operand, return its corresponding
162   string. This routine is used when disassembling the 'CC' instruction.  */
163
164static char *
165getccstring (unsigned cc)
166{
167  return (char *) cr16_b_cond_tab[cc];
168}
169
170
171/* Given a 'cinv' instruction constant operand, return its corresponding
172   string. This routine is used when disassembling the 'cinv' instruction. */
173
174static char *
175getcinvstring (char *str)
176{
177  const cinv_entry *cinv;
178
179  for (cinv = cr16_cinvs; cinv < (cr16_cinvs + NUMCINVS); cinv++)
180    if (strcmp (cinv->istr, str) == 0)
181      return cinv->ostr;
182
183  return ILLEGAL;
184}
185
186/* Given the trap index in dispatch table, return its name.
187   This routine is used when disassembling the 'excp' instruction.  */
188
189static char *
190gettrapstring (unsigned int index)
191{
192  const trap_entry *trap;
193
194  for (trap = cr16_traps; trap < cr16_traps + NUMTRAPS; trap++)
195    if (trap->entry == index)
196      return trap->name;
197
198  return ILLEGAL;
199}
200
201/* Given a register enum value, retrieve its name.  */
202
203static char *
204getregname (reg r)
205{
206  const reg_entry *reg = cr16_regtab + r;
207
208  if (reg->type != CR16_R_REGTYPE)
209    return ILLEGAL;
210
211  return reg->name;
212}
213
214/* Given a register pair enum value, retrieve its name.  */
215
216static char *
217getregpname (reg r)
218{
219  const reg_entry *reg = cr16_regptab + r;
220
221  if (reg->type != CR16_RP_REGTYPE)
222    return ILLEGAL;
223
224  return reg->name;
225}
226
227/* Given a index register pair enum value, retrieve its name.  */
228
229static char *
230getidxregpname (reg r)
231{
232  const reg_entry *reg;
233
234  switch (r)
235   {
236   case 0: r = 0; break;
237   case 1: r = 2; break;
238   case 2: r = 4; break;
239   case 3: r = 6; break;
240   case 4: r = 8; break;
241   case 5: r = 10; break;
242   case 6: r = 3; break;
243   case 7: r = 5; break;
244   default:
245     break;
246   }
247
248  reg = cr16_regptab + r;
249
250  if (reg->type != CR16_RP_REGTYPE)
251    return ILLEGAL;
252
253  return reg->name;
254}
255
256/* Getting a processor register name.  */
257
258static char *
259getprocregname (int index)
260{
261  const reg_entry *r;
262
263  for (r = cr16_pregtab; r < cr16_pregtab + NUMPREGS; r++)
264    if (r->image == index)
265      return r->name;
266
267  return "ILLEGAL REGISTER";
268}
269
270/* Getting a processor register name - 32 bit size.  */
271
272static char *
273getprocpregname (int index)
274{
275  const reg_entry *r;
276
277  for (r = cr16_pregptab; r < cr16_pregptab + NUMPREGPS; r++)
278    if (r->image == index)
279      return r->name;
280
281  return "ILLEGAL REGISTER";
282}
283
284/* START and END are relating 'allWords' struct, which is 48 bits size.
285
286                          START|--------|END
287             +---------+---------+---------+---------+
288             |         |   V    |     A    |   L     |
289             +---------+---------+---------+---------+
290                       0         16        32        48
291    words                  [0]       [1]       [2]      */
292
293static parameter
294makelongparameter (ULONGLONG val, int start, int end)
295{
296  parameter p;
297
298  p.val = (dwordU) EXTRACT (val, 48 - end, end - start);
299  p.nbits = end - start;
300  return p;
301}
302
303/* Build a mask of the instruction's 'constant' opcode,
304   based on the instruction's printing flags.  */
305
306static unsigned long
307build_mask (void)
308{
309  unsigned long mask = SBM (instruction->match_bits);
310  return mask;
311}
312
313/* Search for a matching opcode. Return 1 for success, 0 for failure.  */
314
315static int
316match_opcode (void)
317{
318  unsigned long mask;
319  /* The instruction 'constant' opcode doewsn't exceed 32 bits.  */
320  unsigned long doubleWord = words[1] + (words[0] << 16);
321
322  /* Start searching from end of instruction table.  */
323  instruction = &cr16_instruction[NUMOPCODES - 2];
324
325  /* Loop over instruction table until a full match is found.  */
326  while (instruction >= cr16_instruction)
327    {
328      mask = build_mask ();
329      if ((doubleWord & mask) == BIN (instruction->match,
330                                      instruction->match_bits))
331        return 1;
332      else
333        instruction--;
334    }
335  return 0;
336}
337
338/* Set the proper parameter value for different type of arguments.  */
339
340static void
341make_argument (argument * a, int start_bits)
342{
343  int inst_bit_size;
344  parameter p;
345
346  if ((instruction->size == 3) && a->size >= 16)
347    inst_bit_size = 48;
348  else
349    inst_bit_size = 32;
350
351  switch (a->type)
352    {
353    case arg_r:
354      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
355                             inst_bit_size - start_bits);
356      a->r = p.val;
357      break;
358
359    case arg_rp:
360      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
361                             inst_bit_size - start_bits);
362      a->rp = p.val;
363      break;
364
365    case arg_pr:
366      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
367                             inst_bit_size - start_bits);
368      a->pr = p.val;
369      break;
370
371    case arg_prp:
372      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
373                             inst_bit_size - start_bits);
374      a->prp = p.val;
375      break;
376
377    case arg_ic:
378      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
379                             inst_bit_size - start_bits);
380      a->constant = p.val;
381      break;
382
383    case arg_cc:
384      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
385                             inst_bit_size - start_bits);
386
387      a->cc = p.val;
388      break;
389
390    case arg_idxr:
391      if ((IS_INSN_MNEMONIC ("cbitb"))
392	  || (IS_INSN_MNEMONIC ("sbitb"))
393	  || (IS_INSN_MNEMONIC ("tbitb")))
394	p = makelongparameter (allWords, 8, 9);
395      else
396	p = makelongparameter (allWords, 9, 10);
397      a->i_r = p.val;
398      p = makelongparameter (allWords, inst_bit_size - a->size, inst_bit_size);
399      a->constant = p.val;
400      break;
401
402    case arg_idxrp:
403      p = makelongparameter (allWords, start_bits + 12, start_bits + 13);
404      a->i_r = p.val;
405      p = makelongparameter (allWords, start_bits + 13, start_bits + 16);
406      a->rp = p.val;
407      if (inst_bit_size > 32)
408	{
409	  p = makelongparameter (allWords, inst_bit_size - start_bits - 12,
410				 inst_bit_size);
411	  a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
412	}
413      else if (instruction->size == 2)
414	{
415	  p = makelongparameter (allWords, inst_bit_size - 22, inst_bit_size);
416	  a->constant = (p.val & 0xf) | (((p.val >>20) & 0x3) << 4)
417	    | ((p.val >>14 & 0x3) << 6) | (((p.val >>7) & 0x1f) <<7);
418	}
419      else if (instruction->size == 1 && a->size == 0)
420	a->constant = 0;
421
422      break;
423
424    case arg_rbase:
425      p = makelongparameter (allWords, inst_bit_size, inst_bit_size);
426      a->constant = p.val;
427      p = makelongparameter (allWords, inst_bit_size - (start_bits + 4),
428                             inst_bit_size - start_bits);
429      a->r = p.val;
430      break;
431
432    case arg_cr:
433      p = makelongparameter (allWords, start_bits + 12, start_bits + 16);
434      a->r = p.val;
435      p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size);
436      a->constant = p.val;
437      break;
438
439    case arg_crp:
440      if (instruction->size == 1)
441	p = makelongparameter (allWords, 12, 16);
442      else
443	p = makelongparameter (allWords, start_bits + 12, start_bits + 16);
444      a->rp = p.val;
445
446      if (inst_bit_size > 32)
447	{
448	  p = makelongparameter (allWords, inst_bit_size - start_bits - 12,
449				 inst_bit_size);
450	  a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
451	}
452      else if (instruction->size == 2)
453	{
454	  p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size);
455	  a->constant = p.val;
456	}
457      else if (instruction->size == 1 && a->size != 0)
458	{
459	  p = makelongparameter (allWords, 4, 8);
460	  if (IS_INSN_MNEMONIC ("loadw")
461	      || IS_INSN_MNEMONIC ("loadd")
462	      || IS_INSN_MNEMONIC ("storw")
463	      || IS_INSN_MNEMONIC ("stord"))
464	    a->constant = (p.val * 2);
465	  else
466	    a->constant = p.val;
467	}
468      else /* below case for 0x0(reg pair) */
469	a->constant = 0;
470
471      break;
472
473    case arg_c:
474
475      if ((IS_INSN_TYPE (BRANCH_INS))
476	  || (IS_INSN_MNEMONIC ("bal"))
477	  || (IS_INSN_TYPE (CSTBIT_INS))
478	  || (IS_INSN_TYPE (LD_STOR_INS)))
479	{
480	  switch (a->size)
481	    {
482	    case 8 :
483	      p = makelongparameter (allWords, 0, start_bits);
484	      a->constant = ((((p.val&0xf00)>>4)) | (p.val&0xf));
485	      break;
486
487	    case 24:
488	      if (instruction->size == 3)
489		{
490		  p = makelongparameter (allWords, 16, inst_bit_size);
491		  a->constant = ((((p.val>>16)&0xf) << 20)
492				 | (((p.val>>24)&0xf) << 16)
493				 | (p.val & 0xffff));
494		}
495	      else if (instruction->size == 2)
496		{
497		  p = makelongparameter (allWords, 8, inst_bit_size);
498		  a->constant = p.val;
499		}
500	      break;
501
502	    default:
503	      p = makelongparameter (allWords, inst_bit_size - (start_bits +
504								a->size), inst_bit_size - start_bits);
505	      a->constant = p.val;
506	      break;
507	    }
508	}
509      else
510	{
511	  p = makelongparameter (allWords, inst_bit_size -
512				 (start_bits + a->size),
513				 inst_bit_size - start_bits);
514	  a->constant = p.val;
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  PTR 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      func (stream, "%s", "0x");
673      number = ((relative ? memaddr : 0) +
674		(sign_flag ? ((- a->constant) & 0xffffffe) : a->constant));
675
676      (*info->print_address_func) ((number & ((1 << 24) - 1)), info);
677
678      func (stream, "%s", print_exp_len (instruction->size * 16));
679      break;
680
681    default:
682      break;
683    }
684}
685
686/* Print all the arguments of CURRINSN instruction.  */
687
688static void
689print_arguments (ins *currInsn, bfd_vma memaddr, struct disassemble_info *info)
690{
691  int i;
692
693  /* For "pop/push/popret RA instruction only.  */
694  if ((IS_INSN_MNEMONIC ("pop")
695       || (IS_INSN_MNEMONIC ("popret")
696	   || (IS_INSN_MNEMONIC ("push"))))
697      && currInsn->nargs == 1)
698    {
699      info->fprintf_func (info->stream, "RA");
700      return;
701    }
702
703  for (i = 0; i < currInsn->nargs; i++)
704    {
705      processing_argument_number = i;
706
707      /* For "bal (ra), disp17" instruction only.  */
708      if ((IS_INSN_MNEMONIC ("bal")) && (i == 0) && instruction->size == 2)
709        {
710          info->fprintf_func (info->stream, "(ra),");
711          continue;
712        }
713
714      if ((INST_HAS_REG_LIST) && (i == 2))
715        info->fprintf_func (info->stream, "RA");
716      else
717        print_arg (&currInsn->arg[i], memaddr, info);
718
719      if ((i != currInsn->nargs - 1) && (!IS_INSN_MNEMONIC ("b")))
720        info->fprintf_func (info->stream, ",");
721    }
722}
723
724/* Build the instruction's arguments.  */
725
726static void
727make_instruction (void)
728{
729  int i;
730  unsigned int shift;
731
732  for (i = 0; i < currInsn.nargs; i++)
733    {
734      argument a;
735
736      memset (&a, 0, sizeof (a));
737      a.type = getargtype (instruction->operands[i].op_type);
738      a.size = getbits (instruction->operands[i].op_type);
739      shift = instruction->operands[i].shift;
740
741      make_argument (&a, shift);
742      currInsn.arg[i] = a;
743    }
744
745  /* Calculate instruction size (in bytes).  */
746  currInsn.size = instruction->size + (size_changed ? 1 : 0);
747  /* Now in bits.  */
748  currInsn.size *= 2;
749}
750
751/* Retrieve a single word from a given memory address.  */
752
753static wordU
754get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info)
755{
756  bfd_byte buffer[4];
757  int status;
758  wordU insn = 0;
759
760  status = info->read_memory_func (memaddr, buffer, 2, info);
761
762  if (status == 0)
763    insn = (wordU) bfd_getl16 (buffer);
764
765  return insn;
766}
767
768/* Retrieve multiple words (3) from a given memory address.  */
769
770static void
771get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info)
772{
773  int i;
774  bfd_vma mem;
775
776  for (i = 0, mem = memaddr; i < 3; i++, mem += 2)
777    words[i] = get_word_at_PC (mem, info);
778
779  allWords =
780    ((ULONGLONG) words[0] << 32) + ((unsigned long) words[1] << 16) + words[2];
781}
782
783/* Prints the instruction by calling print_arguments after proper matching.  */
784
785int
786print_insn_cr16 (bfd_vma memaddr, struct disassemble_info *info)
787{
788  int is_decoded;     /* Nonzero means instruction has a match.  */
789
790  /* Initialize global variables.  */
791  imm4flag = 0;
792  size_changed = 0;
793
794  /* Retrieve the encoding from current memory location.  */
795  get_words_at_PC (memaddr, info);
796  /* Find a matching opcode in table.  */
797  is_decoded = match_opcode ();
798  /* If found, print the instruction's mnemonic and arguments.  */
799  if (is_decoded > 0 && (words[0] << 16 || words[1]) != 0)
800    {
801      if (strneq (instruction->mnemonic, "cinv", 4))
802        info->fprintf_func (info->stream,"%s", getcinvstring ((char *)instruction->mnemonic));
803      else
804        info->fprintf_func (info->stream, "%s", instruction->mnemonic);
805
806      if (((currInsn.nargs = get_number_of_operands ()) != 0)
807	  && ! (IS_INSN_MNEMONIC ("b")))
808        info->fprintf_func (info->stream, "\t");
809      make_instruction ();
810      /* For push/pop/pushrtn with RA instructions.  */
811      if ((INST_HAS_REG_LIST) && ((words[0] >> 7) & 0x1))
812        currInsn.nargs +=1;
813      print_arguments (&currInsn, memaddr, info);
814      return currInsn.size;
815    }
816
817  /* No match found.  */
818  info->fprintf_func (info->stream,"%s ",ILLEGAL);
819  return 2;
820}
821