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