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 (&currentInsn->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