cr16-dis.c revision 214634
125537Sdfr/* Disassembler code for CR16.
225537Sdfr   Copyright 2007 Free Software Foundation, Inc.
325537Sdfr   Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com).
425537Sdfr
525537Sdfr   This file is part of GAS, GDB and the GNU binutils.
625537Sdfr
725537Sdfr   This program is free software; you can redistribute it and/or modify it under
825537Sdfr   the terms of the GNU General Public License as published by the Free
925537Sdfr   Software Foundation; either version 2, or (at your option)
1025537Sdfr   any later version.
1125537Sdfr
1225537Sdfr   This program is distributed in the hope that it will be useful, but WITHOUT
1325537Sdfr   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1425537Sdfr   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1525537Sdfr   more details.
1625537Sdfr
1725537Sdfr   You should have received a copy of the GNU General Public License
1825537Sdfr   along with this program; if not, write to the Free Software Foundation,
1925537Sdfr   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2025537Sdfr
2125537Sdfr#include "dis-asm.h"
2225537Sdfr#include "sysdep.h"
2325537Sdfr#include "opcode/cr16.h"
2425537Sdfr#include "libiberty.h"
2525537Sdfr
2643084Speter/* String to print when opcode was not matched.  */
2725537Sdfr#define ILLEGAL  "illegal"
2825537Sdfr  /* Escape to 16-bit immediate.  */
2940159Speter#define ESCAPE_16_BIT  0xB
3040159Speter
3125537Sdfr/* Extract 'n_bits' from 'a' starting from offset 'offs'.  */
3225537Sdfr#define EXTRACT(a, offs, n_bits)                    \
3325537Sdfr  (n_bits == 32 ? (((a) >> (offs)) & 0xffffffffL)   \
3425537Sdfr  : (((a) >> (offs)) & ((1 << (n_bits)) -1)))
3525537Sdfr
3625537Sdfr/* Set Bit Mask - a mask to set all bits starting from offset 'offs'.  */
3725537Sdfr#define SBM(offs)  ((((1 << (32 - offs)) -1) << (offs)))
3825537Sdfr
3925537Sdfrtypedef unsigned long dwordU;
4040159Spetertypedef unsigned short wordU;
4125537Sdfr
4225537Sdfrtypedef struct
4331675Sdyson{
4440159Speter  dwordU val;
4540159Speter  int nbits;
4640159Speter} parameter;
4740159Speter
4840159Speter/* Structure to map valid 'cinv' instruction options.  */
4925537Sdfr
5040961Spetertypedef struct
5140961Speter  {
5240961Speter    /* Cinv printed string.  */
5340961Speter    char *istr;
5432153Sbde    /* Value corresponding to the string.  */
5531324Sbde    char *ostr;
5640906Speter  }
5731324Sbdecinv_entry;
5825537Sdfr
5925537Sdfr/* CR16 'cinv' options mapping.  */
6025537Sdfrconst cinv_entry cr16_cinvs[] =
6125537Sdfr{
6225537Sdfr  {"cinv[i]",     "cinv    [i]"},
6325537Sdfr  {"cinv[i,u]",   "cinv    [i,u]"},
6425537Sdfr  {"cinv[d]",     "cinv    [d]"},
6525537Sdfr  {"cinv[d,u]",   "cinv    [d,u]"},
6625537Sdfr  {"cinv[d,i]",   "cinv    [d,i]"},
6725537Sdfr  {"cinv[d,i,u]", "cinv    [d,i,u]"}
6825537Sdfr};
6925537Sdfr
7025537Sdfr/* Number of valid 'cinv' instruction options.  */
7140159Speterstatic int NUMCINVS = ARRAY_SIZE (cr16_cinvs);
7225537Sdfr
7325537Sdfr/* Enum to distinguish different registers argument types.  */
7425537Sdfrtypedef enum REG_ARG_TYPE
7525537Sdfr  {
7625537Sdfr    /* General purpose register (r<N>).  */
7725537Sdfr    REG_ARG = 0,
7825537Sdfr    /*Processor register   */
7925537Sdfr    P_ARG,
8025537Sdfr  }
8125537SdfrREG_ARG_TYPE;
8240395Speter
8325537Sdfr/* Current opcode table entry we're disassembling.  */
8425537Sdfrconst inst *instruction;
8525537Sdfr/* Current instruction we're disassembling.  */
8625537Sdfrins currInsn;
8725537Sdfr/* The current instruction is read into 3 consecutive words.  */
8825537SdfrwordU words[3];
8925537Sdfr/* Contains all words in appropriate order.  */
9025537SdfrULONGLONG allWords;
9125537Sdfr/* Holds the current processed argument number.  */
9225537Sdfrint processing_argument_number;
9325537Sdfr/* Nonzero means a IMM4 instruction.  */
9425537Sdfrint imm4flag;
9525537Sdfr/* Nonzero means the instruction's original size is
9625537Sdfr   incremented (escape sequence is used).  */
9725537Sdfrint size_changed;
9825537Sdfr
9940159Speter
10025537Sdfr/* Print the constant expression length.  */
10125537Sdfr
10225537Sdfrstatic char *
10325537Sdfrprint_exp_len (int size)
10425537Sdfr{
10525537Sdfr  switch (size)
10640159Speter    {
10740159Speter    case 4:
10825537Sdfr    case 5:
10925537Sdfr    case 6:
11025537Sdfr    case 8:
11140159Speter    case 14:
11240159Speter    case 16:
11340159Speter      return ":s";
11440159Speter    case 20:
11540159Speter    case 24:
11640159Speter    case 32:
11740159Speter      return ":m";
11840159Speter    case 48:
11925537Sdfr      return ":l";
12025537Sdfr    default:
12125537Sdfr      return "";
12225537Sdfr    }
12325537Sdfr}
12425537Sdfr
12525537Sdfr
12641055Speter/* Retrieve the number of operands for the current assembled instruction.  */
12741055Speter
12841055Speterstatic int
12941055Speterget_number_of_operands (void)
13041055Speter{
13125537Sdfr  int i;
13225537Sdfr
13325537Sdfr  for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
13425537Sdfr    ;
13525537Sdfr
13625537Sdfr  return i;
13725537Sdfr}
13825537Sdfr
13925537Sdfr/* Return the bit size for a given operand.  */
14025537Sdfr
14125537Sdfrstatic int
14225537Sdfrgetbits (operand_type op)
14341055Speter{
14441055Speter  if (op < MAX_OPRD)
14525537Sdfr    return cr16_optab[op].bit_size;
14625537Sdfr
14741055Speter  return 0;
14825537Sdfr}
14925537Sdfr
15041055Speter/* Return the argument type of a given operand.  */
15125537Sdfr
15225537Sdfrstatic argtype
15325537Sdfrgetargtype (operand_type op)
15431675Sdyson{
15525537Sdfr  if (op < MAX_OPRD)
15631675Sdyson    return cr16_optab[op].arg_type;
15731675Sdyson
15831675Sdyson  return nullargs;
15931675Sdyson}
16031675Sdyson
16131675Sdyson/* Given a 'CC' instruction constant operand, return its corresponding
16231675Sdyson   string. This routine is used when disassembling the 'CC' instruction.  */
16331675Sdyson
16431675Sdysonstatic char *
16531675Sdysongetccstring (unsigned cc)
16625537Sdfr{
16730994Sphk  return (char *) cr16_b_cond_tab[cc];
16830994Sphk}
16925537Sdfr
17025537Sdfr
17125537Sdfr/* Given a 'cinv' instruction constant operand, return its corresponding
17241055Speter   string. This routine is used when disassembling the 'cinv' instruction. */
17325537Sdfr
17425537Sdfrstatic char *
17525537Sdfrgetcinvstring (char *str)
17625537Sdfr{
17741055Speter  const cinv_entry *cinv;
17841055Speter
17941055Speter  for (cinv = cr16_cinvs; cinv < (cr16_cinvs + NUMCINVS); cinv++)
18041055Speter    if (strcmp (cinv->istr, str) == 0)
18141055Speter      return cinv->ostr;
18241055Speter
18341055Speter  return ILLEGAL;
18441055Speter}
18541055Speter
18641055Speter/* Given the trap index in dispatch table, return its name.
18741055Speter   This routine is used when disassembling the 'excp' instruction.  */
18841055Speter
18941055Speterstatic char *
19041055Spetergettrapstring (unsigned int index)
19141055Speter{
19241055Speter  const trap_entry *trap;
19341055Speter
19441055Speter  for (trap = cr16_traps; trap < cr16_traps + NUMTRAPS; trap++)
19541055Speter    if (trap->entry == index)
19641055Speter      return trap->name;
19741055Speter
19841055Speter  return ILLEGAL;
19941055Speter}
20041055Speter
20141055Speter/* Given a register enum value, retrieve its name.  */
20241055Speter
20341055Speterstatic char *
20441055Spetergetregname (reg r)
20541055Speter{
20641055Speter  const reg_entry *reg = cr16_regtab + r;
20741055Speter
20841055Speter  if (reg->type != CR16_R_REGTYPE)
20941055Speter    return ILLEGAL;
21041055Speter
21141055Speter  return reg->name;
21241055Speter}
21341055Speter
21441055Speter/* Given a register pair enum value, retrieve its name.  */
21541055Speter
21641055Speterstatic char *
21741055Spetergetregpname (reg r)
21841055Speter{
21941055Speter  const reg_entry *reg = cr16_regptab + r;
22041055Speter
22141055Speter  if (reg->type != CR16_RP_REGTYPE)
22241055Speter    return ILLEGAL;
22341055Speter
22441055Speter  return reg->name;
22541055Speter}
22641055Speter
22741055Speter/* Given a index register pair enum value, retrieve its name.  */
22841055Speter
22941055Speterstatic char *
23041055Spetergetidxregpname (reg r)
23141055Speter{
23241055Speter  const reg_entry *reg;
23341055Speter
23441055Speter  switch (r)
23525537Sdfr   {
23625537Sdfr   case 0: r = 0; break;
23725537Sdfr   case 1: r = 2; break;
23825537Sdfr   case 2: r = 4; break;
23925537Sdfr   case 3: r = 6; break;
24042755Speter   case 4: r = 8; break;
24140861Speter   case 5: r = 10; break;
24225537Sdfr   case 6: r = 3; break;
24325537Sdfr   case 7: r = 5; break;
24425537Sdfr   default:
24525537Sdfr     break;
24625537Sdfr   }
24725537Sdfr
24825537Sdfr  reg = cr16_regptab + r;
24925537Sdfr
25025537Sdfr  if (reg->type != CR16_RP_REGTYPE)
25140861Speter    return ILLEGAL;
25240861Speter
25340861Speter  return reg->name;
25440861Speter}
25540861Speter
25640861Speter/* Getting a processor register name.  */
25725537Sdfr
25842755Speterstatic char *
25925537Sdfrgetprocregname (int index)
26025537Sdfr{
26125537Sdfr  const reg_entry *r;
26242755Speter
26342755Speter  for (r = cr16_pregtab; r < cr16_pregtab + NUMPREGS; r++)
26442755Speter    if (r->image == index)
26542755Speter      return r->name;
26642755Speter
26742755Speter  return "ILLEGAL REGISTER";
26842755Speter}
26942755Speter
27042755Speter/* Getting a processor register name - 32 bit size.  */
27142755Speter
27225537Sdfrstatic char *
27325537Sdfrgetprocpregname (int index)
27425537Sdfr{
27525537Sdfr  const reg_entry *r;
27640861Speter
27725537Sdfr  for (r = cr16_pregptab; r < cr16_pregptab + NUMPREGPS; r++)
27825537Sdfr    if (r->image == index)
27925537Sdfr      return r->name;
28042755Speter
28142755Speter  return "ILLEGAL REGISTER";
28242755Speter}
28342755Speter
28442755Speter/* START and END are relating 'allWords' struct, which is 48 bits size.
28542755Speter
28642755Speter                          START|--------|END
28742755Speter             +---------+---------+---------+---------+
28825537Sdfr             |         |   V    |     A    |   L     |
28925537Sdfr             +---------+---------+---------+---------+
29040861Speter                       0         16        32        48
29140861Speter    words                  [0]       [1]       [2]      */
29225537Sdfr
29325537Sdfrstatic parameter
29425537Sdfrmakelongparameter (ULONGLONG val, int start, int end)
29525537Sdfr{
29625537Sdfr  parameter p;
29725537Sdfr
29825537Sdfr  p.val = (dwordU) EXTRACT (val, 48 - end, end - start);
29940861Speter  p.nbits = end - start;
30025537Sdfr  return p;
30140861Speter}
30240861Speter
30340861Speter/* Build a mask of the instruction's 'constant' opcode,
30440861Speter   based on the instruction's printing flags.  */
30540861Speter
30625537Sdfrstatic unsigned long
30740861Speterbuild_mask (void)
30840861Speter{
30940861Speter  unsigned long mask = SBM (instruction->match_bits);
31025537Sdfr  return mask;
31125537Sdfr}
31240861Speter
31325537Sdfr/* Search for a matching opcode. Return 1 for success, 0 for failure.  */
31425537Sdfr
31540861Speterstatic int
31640861Spetermatch_opcode (void)
31740861Speter{
31825537Sdfr  unsigned long mask;
31925537Sdfr  /* The instruction 'constant' opcode doewsn't exceed 32 bits.  */
32025537Sdfr  unsigned long doubleWord = words[1] + (words[0] << 16);
32125537Sdfr
32225537Sdfr  /* Start searching from end of instruction table.  */
32325537Sdfr  instruction = &cr16_instruction[NUMOPCODES - 2];
32425537Sdfr
32525537Sdfr  /* Loop over instruction table until a full match is found.  */
32625537Sdfr  while (instruction >= cr16_instruction)
32725537Sdfr    {
32825537Sdfr      mask = build_mask ();
32925537Sdfr      if ((doubleWord & mask) == BIN (instruction->match,
33025537Sdfr                                      instruction->match_bits))
33125537Sdfr        return 1;
33225537Sdfr      else
33325537Sdfr        instruction--;
33425537Sdfr    }
33525537Sdfr  return 0;
33640159Speter}
33725537Sdfr
33825537Sdfr/* Set the proper parameter value for different type of arguments.  */
33925537Sdfr
34040159Speterstatic void
34125537Sdfrmake_argument (argument * a, int start_bits)
34240159Speter{
34340159Speter  int inst_bit_size;
34440159Speter  parameter p;
34540159Speter
34640159Speter  if ((instruction->size == 3) && a->size >= 16)
34740159Speter    inst_bit_size = 48;
34825537Sdfr  else
34925537Sdfr    inst_bit_size = 32;
35025537Sdfr
35125537Sdfr  switch (a->type)
35225537Sdfr    {
35325537Sdfr    case arg_r:
35440395Speter      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
35525537Sdfr                             inst_bit_size - start_bits);
35625537Sdfr      a->r = p.val;
35725537Sdfr      break;
35825537Sdfr
35925537Sdfr    case arg_rp:
36025537Sdfr      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
36125537Sdfr                             inst_bit_size - start_bits);
36225537Sdfr      a->rp = p.val;
36325537Sdfr      break;
36425537Sdfr
36525537Sdfr    case arg_pr:
36625537Sdfr      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
36725537Sdfr                             inst_bit_size - start_bits);
36825537Sdfr      a->pr = p.val;
36925537Sdfr      break;
37025537Sdfr
37125537Sdfr    case arg_prp:
37225537Sdfr      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
37325537Sdfr                             inst_bit_size - start_bits);
37425537Sdfr      a->prp = p.val;
37525537Sdfr      break;
37625537Sdfr
37725537Sdfr    case arg_ic:
37825537Sdfr      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
37925537Sdfr                             inst_bit_size - start_bits);
38025537Sdfr      a->constant = p.val;
38125537Sdfr      break;
38225537Sdfr
38340159Speter    case arg_cc:
38425537Sdfr      p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
38525537Sdfr                             inst_bit_size - start_bits);
38625537Sdfr
38725537Sdfr      a->cc = p.val;
38825537Sdfr      break;
38925537Sdfr
39025537Sdfr    case arg_idxr:
39125537Sdfr      if ((IS_INSN_MNEMONIC ("cbitb"))
39225537Sdfr	  || (IS_INSN_MNEMONIC ("sbitb"))
39325537Sdfr	  || (IS_INSN_MNEMONIC ("tbitb")))
39425537Sdfr	p = makelongparameter (allWords, 8, 9);
39525537Sdfr      else
39625537Sdfr	p = makelongparameter (allWords, 9, 10);
39725537Sdfr      a->i_r = p.val;
39825537Sdfr      p = makelongparameter (allWords, inst_bit_size - a->size, inst_bit_size);
39925537Sdfr      a->constant = p.val;
40025537Sdfr      break;
40125537Sdfr
40225537Sdfr    case arg_idxrp:
40325537Sdfr      p = makelongparameter (allWords, start_bits + 12, start_bits + 13);
40425537Sdfr      a->i_r = p.val;
40525537Sdfr      p = makelongparameter (allWords, start_bits + 13, start_bits + 16);
40625537Sdfr      a->rp = p.val;
40725537Sdfr      if (inst_bit_size > 32)
40825537Sdfr	{
40925537Sdfr	  p = makelongparameter (allWords, inst_bit_size - start_bits - 12,
41025537Sdfr				 inst_bit_size);
41125537Sdfr	  a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
41225537Sdfr	}
41341055Speter      else if (instruction->size == 2)
41441055Speter	{
41525537Sdfr	  p = makelongparameter (allWords, inst_bit_size - 22, inst_bit_size);
41625537Sdfr	  a->constant = (p.val & 0xf) | (((p.val >>20) & 0x3) << 4)
41740159Speter	    | ((p.val >>14 & 0x3) << 6) | (((p.val >>7) & 0x1f) <<7);
41825537Sdfr	}
41925537Sdfr      else if (instruction->size == 1 && a->size == 0)
42025537Sdfr	a->constant = 0;
42125537Sdfr
42225537Sdfr      break;
42325537Sdfr
42425537Sdfr    case arg_rbase:
42525537Sdfr      p = makelongparameter (allWords, inst_bit_size, inst_bit_size);
42625537Sdfr      a->constant = p.val;
42725537Sdfr      p = makelongparameter (allWords, inst_bit_size - (start_bits + 4),
42825537Sdfr                             inst_bit_size - start_bits);
42925537Sdfr      a->r = p.val;
43025537Sdfr      break;
43125537Sdfr
43225537Sdfr    case arg_cr:
43325537Sdfr      p = makelongparameter (allWords, start_bits + 12, start_bits + 16);
43425537Sdfr      a->r = p.val;
43525537Sdfr      p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size);
43625537Sdfr      a->constant = p.val;
43725537Sdfr      break;
43825537Sdfr
43925537Sdfr    case arg_crp:
44025537Sdfr      if (instruction->size == 1)
44125537Sdfr	p = makelongparameter (allWords, 12, 16);
44225537Sdfr      else
44325537Sdfr	p = makelongparameter (allWords, start_bits + 12, start_bits + 16);
44440395Speter      a->rp = p.val;
44525537Sdfr
44625537Sdfr      if (inst_bit_size > 32)
44725537Sdfr	{
44825537Sdfr	  p = makelongparameter (allWords, inst_bit_size - start_bits - 12,
44925537Sdfr				 inst_bit_size);
45025537Sdfr	  a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
45125537Sdfr	}
45225537Sdfr      else if (instruction->size == 2)
45325537Sdfr	{
45425537Sdfr	  p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size);
45525537Sdfr	  a->constant = p.val;
45625537Sdfr	}
45725537Sdfr      else if (instruction->size == 1 && a->size != 0)
45825537Sdfr	{
45925537Sdfr	  p = makelongparameter (allWords, 4, 8);
46038275Sdfr	  if (IS_INSN_MNEMONIC ("loadw")
46138275Sdfr	      || IS_INSN_MNEMONIC ("loadd")
46242849Speter	      || IS_INSN_MNEMONIC ("storw")
46325537Sdfr	      || IS_INSN_MNEMONIC ("stord"))
46425537Sdfr	    a->constant = (p.val * 2);
46525537Sdfr	  else
46625537Sdfr	    a->constant = p.val;
46740159Speter	}
46825537Sdfr      else /* below case for 0x0(reg pair) */
46925537Sdfr	a->constant = 0;
47038275Sdfr
47138275Sdfr      break;
47238275Sdfr
47325537Sdfr    case arg_c:
47425537Sdfr
47525537Sdfr      if ((IS_INSN_TYPE (BRANCH_INS))
47625537Sdfr	  || (IS_INSN_MNEMONIC ("bal"))
47738275Sdfr	  || (IS_INSN_TYPE (CSTBIT_INS))
47840159Speter	  || (IS_INSN_TYPE (LD_STOR_INS)))
47940159Speter	{
48038275Sdfr	  switch (a->size)
48140159Speter	    {
48238275Sdfr	    case 8 :
48325537Sdfr	      p = makelongparameter (allWords, 0, start_bits);
48442849Speter	      a->constant = ((((p.val&0xf00)>>4)) | (p.val&0xf));
48525537Sdfr	      break;
48625537Sdfr
48740159Speter	    case 24:
48840159Speter	      if (instruction->size == 3)
48925537Sdfr		{
49040159Speter		  p = makelongparameter (allWords, 16, inst_bit_size);
49125537Sdfr		  a->constant = ((((p.val>>16)&0xf) << 20)
49225537Sdfr				 | (((p.val>>24)&0xf) << 16)
49342849Speter				 | (p.val & 0xffff));
49442849Speter		}
49542849Speter	      else if (instruction->size == 2)
49642849Speter		{
49742849Speter		  p = makelongparameter (allWords, 8, inst_bit_size);
49842849Speter		  a->constant = p.val;
49942849Speter		}
50042849Speter	      break;
50142849Speter
50242849Speter	    default:
50342849Speter	      p = makelongparameter (allWords, inst_bit_size - (start_bits +
50442849Speter								a->size), inst_bit_size - start_bits);
50542849Speter	      a->constant = p.val;
50642849Speter	      break;
50742849Speter	    }
50842849Speter	}
50942849Speter      else
51042849Speter	{
51142849Speter	  p = makelongparameter (allWords, inst_bit_size -
51225537Sdfr				 (start_bits + a->size),
51325537Sdfr				 inst_bit_size - start_bits);
51425537Sdfr	  a->constant = p.val;
51525537Sdfr	}
51625537Sdfr      break;
51725537Sdfr
51825537Sdfr    default:
51925537Sdfr      break;
52025537Sdfr    }
52125537Sdfr}
52240159Speter
52340159Speter/*  Print a single argument.  */
52425537Sdfr
52540159Speterstatic void
52625537Sdfrprint_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info)
52725537Sdfr{
52825537Sdfr  LONGLONG longdisp, mask;
52925537Sdfr  int sign_flag = 0;
53025537Sdfr  int relative = 0;
53125537Sdfr  bfd_vma number;
53225537Sdfr  PTR stream = info->stream;
53325537Sdfr  fprintf_ftype func = info->fprintf_func;
53425537Sdfr
53540159Speter  switch (a->type)
53640159Speter    {
53725537Sdfr    case arg_r:
53840159Speter      func (stream, "%s", getregname (a->r));
53940395Speter      break;
54025537Sdfr
54125537Sdfr    case arg_rp:
54225537Sdfr      func (stream, "%s", getregpname (a->rp));
54325537Sdfr      break;
54425537Sdfr
54525537Sdfr    case arg_pr:
54625537Sdfr      func (stream, "%s", getprocregname (a->pr));
54740159Speter      break;
54825537Sdfr
54925537Sdfr    case arg_prp:
55025537Sdfr      func (stream, "%s", getprocpregname (a->prp));
55140159Speter      break;
55225537Sdfr
55325537Sdfr    case arg_cc:
55425537Sdfr      func (stream, "%s", getccstring (a->cc));
55540159Speter      func (stream, "%s", "\t");
55625537Sdfr      break;
55740159Speter
55840159Speter    case arg_ic:
55940159Speter      if (IS_INSN_MNEMONIC ("excp"))
56040159Speter	{
56140159Speter	  func (stream, "%s", gettrapstring (a->constant));
56240159Speter	  break;
56340159Speter	}
56440159Speter      else if ((IS_INSN_TYPE (ARITH_INS) || IS_INSN_TYPE (ARITH_BYTE_INS))
56540159Speter	       && ((instruction->size == 1) && (a->constant == 9)))
56640159Speter	func (stream, "$%d", -1);
56740159Speter      else if (INST_HAS_REG_LIST)
56840159Speter	func (stream, "$0x%lx", a->constant +1);
56940159Speter      else if (IS_INSN_TYPE (SHIFT_INS))
57040159Speter	{
57140159Speter	  longdisp = a->constant;
57240159Speter	  mask = ((LONGLONG)1 << a->size) - 1;
57340159Speter	  if (longdisp & ((LONGLONG)1 << (a->size -1)))
57440159Speter	    {
57540159Speter	      sign_flag = 1;
57640159Speter	      longdisp = ~(longdisp) + 1;
57740159Speter	    }
57840159Speter	  a->constant = (unsigned long int) (longdisp & mask);
57940159Speter	  func (stream, "$%d", ((int)(sign_flag ? -a->constant :
58040159Speter				      a->constant)));
58140159Speter	}
58240159Speter      else
58340159Speter	func (stream, "$0x%lx", a->constant);
58440159Speter      switch (a->size)
58540159Speter	{
58640159Speter	case 4  : case 5  : case 6  : case 8  :
58740159Speter	  func (stream, "%s", ":s"); break;
58840159Speter	case 16 : case 20 : func (stream, "%s", ":m"); break;
58940159Speter	case 24 : case 32 : func (stream, "%s", ":l"); break;
59040159Speter	default: break;
59140159Speter	}
59240159Speter      break;
59340159Speter
59440159Speter    case arg_idxr:
59540159Speter      if (a->i_r == 0) func (stream, "[r12]");
59640159Speter      if (a->i_r == 1) func (stream, "[r13]");
59740159Speter      func (stream, "0x%lx", a->constant);
59840159Speter      func (stream, "%s", print_exp_len (instruction->size * 16));
59940159Speter      break;
60040159Speter
60140159Speter    case arg_idxrp:
60240159Speter      if (a->i_r == 0) func (stream, "[r12]");
60340159Speter      if (a->i_r == 1) func (stream, "[r13]");
60440159Speter      func (stream, "0x%lx", a->constant);
60540159Speter      func (stream, "%s", print_exp_len (instruction->size * 16));
60640159Speter      func (stream, "%s", getidxregpname (a->rp));
60740159Speter      break;
60840159Speter
60940159Speter    case arg_rbase:
61040159Speter      func (stream, "(%s)", getregname (a->r));
61140159Speter      break;
61240159Speter
61340159Speter    case arg_cr:
61440159Speter      func (stream, "0x%lx", a->constant);
61540159Speter      func (stream, "%s", print_exp_len (instruction->size * 16));
61640159Speter      func (stream, "(%s)", getregname (a->r));
61740159Speter      break;
61840159Speter
61940159Speter    case arg_crp:
62040159Speter      func (stream, "0x%lx", a->constant);
62140159Speter      func (stream, "%s", print_exp_len (instruction->size * 16));
62240159Speter      func (stream, "%s", getregpname (a->rp));
62340159Speter      break;
62425537Sdfr
62525537Sdfr    case arg_c:
62625537Sdfr      /*Removed the *2 part as because implicit zeros are no more required.
62725537Sdfr	Have to fix this as this needs a bit of extension in terms of branch
62830994Sphk	instructions. */
62925537Sdfr      if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal"))
63042316Smsmith	{
63125537Sdfr	  relative = 1;
63225537Sdfr	  longdisp = a->constant;
63325537Sdfr	  /* REVISIT: To sync with WinIDEA and CR16 4.1tools, the below
63430994Sphk	     line commented */
63525537Sdfr	  /* longdisp <<= 1; */
63625537Sdfr	  mask = ((LONGLONG)1 << a->size) - 1;
63725537Sdfr	  switch (a->size)
63825537Sdfr	    {
63925537Sdfr	    case 8  :
64025537Sdfr	      {
64125537Sdfr		longdisp <<= 1;
64225537Sdfr		if (longdisp & ((LONGLONG)1 << a->size))
64325537Sdfr		  {
64425537Sdfr		    sign_flag = 1;
64525537Sdfr		    longdisp = ~(longdisp) + 1;
64642316Smsmith		  }
64742316Smsmith		break;
64842316Smsmith	      }
64942316Smsmith	    case 16 :
65042316Smsmith	    case 24 :
65142316Smsmith	      {
65242316Smsmith		if (longdisp & 1)
65342316Smsmith		  {
65442316Smsmith		    sign_flag = 1;
65540859Speter		    longdisp = ~(longdisp) + 1;
65625537Sdfr		  }
65725537Sdfr		break;
65825537Sdfr	      }
65930994Sphk	    default:
66040159Speter	      func (stream, "Wrong offset used in branch/bal instruction");
66125537Sdfr	      break;
66225537Sdfr	    }
66325537Sdfr	  a->constant = (unsigned long int) (longdisp & mask);
66425537Sdfr	}
66525537Sdfr      /* For branch Neq instruction it is 2*offset + 2.  */
66625537Sdfr      else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
66725537Sdfr	a->constant = 2 * a->constant + 2;
66830994Sphk
66925537Sdfr      if ((!IS_INSN_TYPE (CSTBIT_INS)) && (!IS_INSN_TYPE (LD_STOR_INS)))
67025537Sdfr	(sign_flag) ? func (stream, "%s", "*-"): func (stream, "%s","*+");
67125537Sdfr
67225537Sdfr      func (stream, "%s", "0x");
67325537Sdfr      number = ((relative ? memaddr : 0) +
67425537Sdfr		(sign_flag ? ((- a->constant) & 0xffffffe) : a->constant));
67525537Sdfr
67625537Sdfr      (*info->print_address_func) ((number & ((1 << 24) - 1)), info);
67725537Sdfr
67825537Sdfr      func (stream, "%s", print_exp_len (instruction->size * 16));
67925537Sdfr      break;
68025537Sdfr
68125537Sdfr    default:
68225537Sdfr      break;
68343084Speter    }
68425537Sdfr}
68525537Sdfr
68625537Sdfr/* Print all the arguments of CURRINSN instruction.  */
68743084Speter
68842837Speterstatic void
68942837Speterprint_arguments (ins *currInsn, bfd_vma memaddr, struct disassemble_info *info)
69043084Speter{
69125537Sdfr  int i;
69225537Sdfr
69325537Sdfr  /* For "pop/push/popret RA instruction only.  */
69425537Sdfr  if ((IS_INSN_MNEMONIC ("pop")
69525537Sdfr       || (IS_INSN_MNEMONIC ("popret")
69625537Sdfr	   || (IS_INSN_MNEMONIC ("push"))))
69725537Sdfr      && currInsn->nargs == 1)
69825537Sdfr    {
69930994Sphk      info->fprintf_func (info->stream, "RA");
70025537Sdfr      return;
70142316Smsmith    }
70225537Sdfr
70325537Sdfr  for (i = 0; i < currInsn->nargs; i++)
70425537Sdfr    {
70530994Sphk      processing_argument_number = i;
70625537Sdfr
70725537Sdfr      /* For "bal (ra), disp17" instruction only.  */
70825537Sdfr      if ((IS_INSN_MNEMONIC ("bal")) && (i == 0) && instruction->size == 2)
70925537Sdfr        {
71025537Sdfr          info->fprintf_func (info->stream, "(ra),");
71142316Smsmith          continue;
71242316Smsmith        }
71342316Smsmith
71442316Smsmith      if ((INST_HAS_REG_LIST) && (i == 2))
71542316Smsmith        info->fprintf_func (info->stream, "RA");
71625537Sdfr      else
71730994Sphk        print_arg (&currInsn->arg[i], memaddr, info);
71825537Sdfr
71925537Sdfr      if ((i != currInsn->nargs - 1) && (!IS_INSN_MNEMONIC ("b")))
72040159Speter        info->fprintf_func (info->stream, ",");
72125537Sdfr    }
72225537Sdfr}
72325537Sdfr
72425537Sdfr/* Build the instruction's arguments.  */
72525537Sdfr
72625537Sdfrstatic void
72725537Sdfrmake_instruction (void)
72830994Sphk{
72925537Sdfr  int i;
73025537Sdfr  unsigned int shift;
73125537Sdfr
73225537Sdfr  for (i = 0; i < currInsn.nargs; i++)
73325537Sdfr    {
73425537Sdfr      argument a;
73530994Sphk
73625537Sdfr      memset (&a, 0, sizeof (a));
73730994Sphk      a.type = getargtype (instruction->operands[i].op_type);
73825537Sdfr      a.size = getbits (instruction->operands[i].op_type);
73925537Sdfr      shift = instruction->operands[i].shift;
74040159Speter
74125537Sdfr      make_argument (&a, shift);
74225537Sdfr      currInsn.arg[i] = a;
74325537Sdfr    }
74430994Sphk
74525537Sdfr  /* Calculate instruction size (in bytes).  */
74630994Sphk  currInsn.size = instruction->size + (size_changed ? 1 : 0);
74725537Sdfr  /* Now in bits.  */
74825537Sdfr  currInsn.size *= 2;
74925537Sdfr}
75025537Sdfr
75125537Sdfr/* Retrieve a single word from a given memory address.  */
75225537Sdfr
75325537Sdfrstatic wordU
75430994Sphkget_word_at_PC (bfd_vma memaddr, struct disassemble_info *info)
75525537Sdfr{
75625537Sdfr  bfd_byte buffer[4];
75725537Sdfr  int status;
75825537Sdfr  wordU insn = 0;
75925537Sdfr
76025537Sdfr  status = info->read_memory_func (memaddr, buffer, 2, info);
76125537Sdfr
76225537Sdfr  if (status == 0)
76325537Sdfr    insn = (wordU) bfd_getl16 (buffer);
76425537Sdfr
76525537Sdfr  return insn;
76625537Sdfr}
76725537Sdfr
76825537Sdfr/* Retrieve multiple words (3) from a given memory address.  */
76925537Sdfr
77025537Sdfrstatic void
77125537Sdfrget_words_at_PC (bfd_vma memaddr, struct disassemble_info *info)
77225537Sdfr{
77325537Sdfr  int i;
77425537Sdfr  bfd_vma mem;
77525537Sdfr
77625537Sdfr  for (i = 0, mem = memaddr; i < 3; i++, mem += 2)
77725537Sdfr    words[i] = get_word_at_PC (mem, info);
77825537Sdfr
77925537Sdfr  allWords =
78025537Sdfr    ((ULONGLONG) words[0] << 32) + ((unsigned long) words[1] << 16) + words[2];
78125537Sdfr}
78225537Sdfr
78325537Sdfr/* Prints the instruction by calling print_arguments after proper matching.  */
78425537Sdfr
78525537Sdfrint
78625537Sdfrprint_insn_cr16 (bfd_vma memaddr, struct disassemble_info *info)
78725537Sdfr{
78825537Sdfr  int is_decoded;     /* Nonzero means instruction has a match.  */
78925537Sdfr
79025537Sdfr  /* Initialize global variables.  */
79125537Sdfr  imm4flag = 0;
79225537Sdfr  size_changed = 0;
79325537Sdfr
79430994Sphk  /* Retrieve the encoding from current memory location.  */
79525537Sdfr  get_words_at_PC (memaddr, info);
79625537Sdfr  /* Find a matching opcode in table.  */
79725537Sdfr  is_decoded = match_opcode ();
79825537Sdfr  /* If found, print the instruction's mnemonic and arguments.  */
79925537Sdfr  if (is_decoded > 0 && (words[0] << 16 || words[1]) != 0)
80025537Sdfr    {
80130994Sphk      if (strneq (instruction->mnemonic, "cinv", 4))
80225537Sdfr        info->fprintf_func (info->stream,"%s", getcinvstring ((char *)instruction->mnemonic));
80325537Sdfr      else
80425537Sdfr        info->fprintf_func (info->stream, "%s", instruction->mnemonic);
80525537Sdfr
80625537Sdfr      if (((currInsn.nargs = get_number_of_operands ()) != 0)
80725537Sdfr	  && ! (IS_INSN_MNEMONIC ("b")))
80825537Sdfr        info->fprintf_func (info->stream, "\t");
80930994Sphk      make_instruction ();
81025537Sdfr      /* For push/pop/pushrtn with RA instructions.  */
81130994Sphk      if ((INST_HAS_REG_LIST) && ((words[0] >> 7) & 0x1))
81225537Sdfr        currInsn.nargs +=1;
81325537Sdfr      print_arguments (&currInsn, memaddr, info);
81425537Sdfr      return currInsn.size;
81525537Sdfr    }
81625537Sdfr
81740159Speter  /* No match found.  */
81841090Speter  info->fprintf_func (info->stream,"%s ",ILLEGAL);
81941090Speter  return 2;
82041090Speter}
82141090Speter