Home | History | Annotate | Line # | Download | only in opcodes
arc-dis.c revision 1.11
      1   1.1  christos /* Instruction printing code for the ARC.
      2  1.11  christos    Copyright (C) 1994-2024 Free Software Foundation, Inc.
      3   1.6  christos 
      4   1.6  christos    Contributed by Claudiu Zissulescu (claziss (at) synopsys.com)
      5   1.1  christos 
      6   1.1  christos    This file is part of libopcodes.
      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.6  christos #include <stdio.h>
     25   1.6  christos #include <assert.h>
     26   1.1  christos #include "dis-asm.h"
     27   1.1  christos #include "opcode/arc.h"
     28   1.6  christos #include "elf/arc.h"
     29   1.6  christos #include "arc-dis.h"
     30   1.6  christos #include "arc-ext.h"
     31   1.1  christos #include "elf-bfd.h"
     32   1.6  christos #include "libiberty.h"
     33   1.1  christos #include "opintl.h"
     34   1.1  christos 
     35   1.6  christos /* Structure used to iterate over, and extract the values for, operands of
     36   1.6  christos    an opcode.  */
     37   1.6  christos 
     38   1.6  christos struct arc_operand_iterator
     39   1.6  christos {
     40   1.7  christos   /* The complete instruction value to extract operands from.  */
     41   1.7  christos   unsigned long long insn;
     42   1.7  christos 
     43   1.7  christos   /* The LIMM if this is being tracked separately.  This field is only
     44   1.7  christos      valid if we find the LIMM operand in the operand list.  */
     45   1.7  christos   unsigned limm;
     46   1.7  christos 
     47   1.7  christos   /* The opcode this iterator is operating on.  */
     48   1.7  christos   const struct arc_opcode *opcode;
     49   1.7  christos 
     50   1.7  christos   /* The index into the opcodes operand index list.  */
     51   1.7  christos   const unsigned char *opidx;
     52   1.7  christos };
     53   1.7  christos 
     54   1.7  christos /* A private data used by ARC decoder.  */
     55   1.7  christos struct arc_disassemble_info
     56   1.7  christos {
     57   1.7  christos   /* The current disassembled arc opcode.  */
     58   1.7  christos   const struct arc_opcode *opcode;
     59   1.7  christos 
     60   1.7  christos   /* Instruction length w/o limm field.  */
     61   1.7  christos   unsigned insn_len;
     62   1.7  christos 
     63   1.7  christos   /* TRUE if we have limm.  */
     64  1.10  christos   bool limm_p;
     65   1.6  christos 
     66   1.7  christos   /* LIMM value, if exists.  */
     67   1.7  christos   unsigned limm;
     68   1.6  christos 
     69   1.7  christos   /* Condition code, if exists.  */
     70   1.7  christos   unsigned condition_code;
     71   1.6  christos 
     72   1.7  christos   /* Writeback mode.  */
     73   1.7  christos   unsigned writeback_mode;
     74   1.6  christos 
     75   1.7  christos   /* Number of operands.  */
     76   1.7  christos   unsigned operands_count;
     77   1.6  christos 
     78   1.7  christos   struct arc_insn_operand operands[MAX_INSN_ARGS];
     79   1.6  christos };
     80   1.6  christos 
     81   1.6  christos /* Globals variables.  */
     82   1.6  christos 
     83   1.6  christos static const char * const regnames[64] =
     84   1.6  christos {
     85   1.6  christos   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
     86   1.6  christos   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
     87   1.6  christos   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
     88   1.6  christos   "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
     89   1.6  christos 
     90   1.6  christos   "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
     91   1.6  christos   "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
     92   1.6  christos   "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
     93   1.9  christos   "r56", "r57", "r58", "r59", "lp_count", "reserved", "LIMM", "pcl"
     94   1.6  christos };
     95   1.6  christos 
     96   1.6  christos static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
     97   1.6  christos {
     98   1.6  christos   "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd",
     99   1.6  christos   "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd"
    100   1.6  christos };
    101   1.6  christos 
    102   1.6  christos static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1;
    103   1.1  christos 
    104   1.6  christos static const char * const addrtypeunknown = "unknown";
    105   1.1  christos 
    106   1.6  christos /* This structure keeps track which instruction class(es)
    107   1.6  christos    should be ignored durring disassembling.  */
    108   1.1  christos 
    109   1.6  christos typedef struct skipclass
    110   1.1  christos {
    111   1.6  christos   insn_class_t     insn_class;
    112   1.6  christos   insn_subclass_t  subclass;
    113   1.6  christos   struct skipclass *nxt;
    114   1.6  christos } skipclass_t, *linkclass;
    115   1.6  christos 
    116   1.6  christos /* Intial classes of instructions to be consider first when
    117   1.6  christos    disassembling.  */
    118   1.6  christos static linkclass decodelist = NULL;
    119   1.6  christos 
    120   1.8  christos /* ISA mask value enforced via disassembler info options.  ARC_OPCODE_NONE
    121   1.8  christos    value means that no CPU is enforced.  */
    122   1.8  christos 
    123   1.8  christos static unsigned enforced_isa_mask = ARC_OPCODE_NONE;
    124   1.8  christos 
    125   1.8  christos /* True if we want to print using only hex numbers.  */
    126  1.10  christos static bool print_hex = false;
    127   1.8  christos 
    128   1.6  christos /* Macros section.  */
    129   1.6  christos 
    130   1.6  christos #ifdef DEBUG
    131   1.6  christos # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
    132   1.6  christos #else
    133   1.6  christos # define pr_debug(fmt, args...)
    134   1.6  christos #endif
    135   1.6  christos 
    136   1.6  christos #define ARRANGE_ENDIAN(info, buf)					\
    137   1.6  christos   (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf))	\
    138   1.6  christos    : bfd_getb32 (buf))
    139   1.1  christos 
    140   1.9  christos #define BITS(word,s,e)  (((word) >> (s)) & ((1ull << ((e) - (s)) << 1) - 1))
    141   1.7  christos #define OPCODE_32BIT_INSN(word)	(BITS ((word), 27, 31))
    142   1.1  christos 
    143   1.6  christos /* Functions implementation.  */
    144   1.1  christos 
    145   1.7  christos /* Initialize private data.  */
    146  1.10  christos static bool
    147   1.7  christos init_arc_disasm_info (struct disassemble_info *info)
    148   1.1  christos {
    149   1.7  christos   struct arc_disassemble_info *arc_infop
    150  1.11  christos     = calloc (1, sizeof (*arc_infop));
    151   1.7  christos 
    152   1.7  christos   if (arc_infop == NULL)
    153  1.10  christos     return false;
    154   1.7  christos 
    155   1.7  christos   info->private_data = arc_infop;
    156  1.10  christos   return true;
    157   1.1  christos }
    158   1.1  christos 
    159   1.6  christos /* Add a new element to the decode list.  */
    160   1.6  christos 
    161   1.6  christos static void
    162   1.6  christos add_to_decodelist (insn_class_t     insn_class,
    163   1.6  christos 		   insn_subclass_t  subclass)
    164   1.1  christos {
    165   1.6  christos   linkclass t = (linkclass) xmalloc (sizeof (skipclass_t));
    166   1.6  christos 
    167   1.6  christos   t->insn_class = insn_class;
    168   1.6  christos   t->subclass = subclass;
    169   1.6  christos   t->nxt = decodelist;
    170   1.6  christos   decodelist = t;
    171   1.1  christos }
    172   1.1  christos 
    173   1.6  christos /* Return TRUE if we need to skip the opcode from being
    174   1.6  christos    disassembled.  */
    175   1.6  christos 
    176  1.10  christos static bool
    177   1.7  christos skip_this_opcode (const struct arc_opcode *opcode)
    178   1.1  christos {
    179   1.6  christos   linkclass t = decodelist;
    180   1.6  christos 
    181   1.6  christos   /* Check opcode for major 0x06, return if it is not in.  */
    182   1.7  christos   if (arc_opcode_len (opcode) == 4
    183   1.9  christos       && (OPCODE_32BIT_INSN (opcode->opcode) != 0x06
    184   1.9  christos 	  /* Can be an APEX extensions.  */
    185   1.9  christos 	  && OPCODE_32BIT_INSN (opcode->opcode) != 0x07))
    186  1.10  christos     return false;
    187   1.6  christos 
    188   1.7  christos   /* or not a known truble class.  */
    189   1.7  christos   switch (opcode->insn_class)
    190   1.7  christos     {
    191   1.7  christos     case FLOAT:
    192   1.7  christos     case DSP:
    193   1.8  christos     case ARITH:
    194   1.9  christos     case MPY:
    195   1.7  christos       break;
    196   1.7  christos     default:
    197  1.10  christos       return false;
    198   1.7  christos     }
    199   1.7  christos 
    200   1.7  christos   while (t != NULL)
    201   1.6  christos     {
    202   1.6  christos       if ((t->insn_class == opcode->insn_class)
    203   1.6  christos 	  && (t->subclass == opcode->subclass))
    204  1.10  christos 	return false;
    205   1.6  christos       t = t->nxt;
    206   1.6  christos     }
    207   1.1  christos 
    208  1.10  christos   return true;
    209   1.1  christos }
    210   1.1  christos 
    211   1.6  christos static bfd_vma
    212   1.6  christos bfd_getm32 (unsigned int data)
    213   1.1  christos {
    214   1.6  christos   bfd_vma value = 0;
    215   1.6  christos 
    216   1.6  christos   value = ((data & 0xff00) | (data & 0xff)) << 16;
    217   1.6  christos   value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
    218   1.6  christos   return value;
    219   1.1  christos }
    220   1.1  christos 
    221  1.10  christos static bool
    222   1.6  christos special_flag_p (const char *opname,
    223   1.6  christos 		const char *flgname)
    224   1.1  christos {
    225   1.6  christos   const struct arc_flag_special *flg_spec;
    226   1.6  christos   unsigned i, j, flgidx;
    227   1.1  christos 
    228   1.6  christos   for (i = 0; i < arc_num_flag_special; i++)
    229   1.1  christos     {
    230   1.6  christos       flg_spec = &arc_flag_special_cases[i];
    231   1.6  christos 
    232   1.6  christos       if (strcmp (opname, flg_spec->name))
    233   1.6  christos 	continue;
    234   1.6  christos 
    235   1.6  christos       /* Found potential special case instruction.  */
    236   1.6  christos       for (j=0;; ++j)
    237   1.6  christos 	{
    238   1.6  christos 	  flgidx = flg_spec->flags[j];
    239   1.6  christos 	  if (flgidx == 0)
    240   1.6  christos 	    break; /* End of the array.  */
    241   1.1  christos 
    242   1.6  christos 	  if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
    243  1.10  christos 	    return true;
    244   1.6  christos 	}
    245   1.1  christos     }
    246  1.10  christos   return false;
    247   1.1  christos }
    248   1.1  christos 
    249   1.6  christos /* Find opcode from ARC_TABLE given the instruction described by INSN and
    250   1.6  christos    INSNLEN.  The ISA_MASK restricts the possible matches in ARC_TABLE.  */
    251   1.6  christos 
    252   1.6  christos static const struct arc_opcode *
    253   1.6  christos find_format_from_table (struct disassemble_info *info,
    254   1.6  christos 			const struct arc_opcode *arc_table,
    255   1.7  christos                         unsigned long long insn,
    256   1.6  christos 			unsigned int insn_len,
    257   1.6  christos                         unsigned isa_mask,
    258  1.10  christos 			bool *has_limm,
    259  1.10  christos 			bool overlaps)
    260   1.1  christos {
    261   1.6  christos   unsigned int i = 0;
    262   1.6  christos   const struct arc_opcode *opcode = NULL;
    263   1.7  christos   const struct arc_opcode *t_op = NULL;
    264   1.6  christos   const unsigned char *opidx;
    265   1.6  christos   const unsigned char *flgidx;
    266  1.10  christos   bool warn_p = false;
    267   1.6  christos 
    268   1.6  christos   do
    269   1.6  christos     {
    270  1.10  christos       bool invalid = false;
    271   1.6  christos 
    272   1.6  christos       opcode = &arc_table[i++];
    273   1.6  christos 
    274   1.7  christos       if (!(opcode->cpu & isa_mask))
    275   1.6  christos 	continue;
    276   1.6  christos 
    277   1.7  christos       if (arc_opcode_len (opcode) != (int) insn_len)
    278   1.6  christos 	continue;
    279   1.6  christos 
    280   1.7  christos       if ((insn & opcode->mask) != opcode->opcode)
    281   1.6  christos 	continue;
    282   1.6  christos 
    283  1.10  christos       *has_limm = false;
    284   1.6  christos 
    285   1.6  christos       /* Possible candidate, check the operands.  */
    286   1.6  christos       for (opidx = opcode->operands; *opidx; opidx++)
    287   1.6  christos 	{
    288   1.7  christos 	  int value, limmind;
    289   1.6  christos 	  const struct arc_operand *operand = &arc_operands[*opidx];
    290   1.6  christos 
    291   1.6  christos 	  if (operand->flags & ARC_OPERAND_FAKE)
    292   1.6  christos 	    continue;
    293   1.6  christos 
    294   1.6  christos 	  if (operand->extract)
    295   1.7  christos 	    value = (*operand->extract) (insn, &invalid);
    296   1.6  christos 	  else
    297   1.9  christos 	    value = (insn >> operand->shift) & ((1ull << operand->bits) - 1);
    298   1.6  christos 
    299   1.6  christos 	  /* Check for LIMM indicator.  If it is there, then make sure
    300   1.6  christos 	     we pick the right format.  */
    301   1.7  christos 	  limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
    302   1.6  christos 	  if (operand->flags & ARC_OPERAND_IR
    303   1.6  christos 	      && !(operand->flags & ARC_OPERAND_LIMM))
    304   1.1  christos 	    {
    305   1.6  christos 	      if ((value == 0x3E && insn_len == 4)
    306   1.7  christos 		  || (value == limmind && insn_len == 2))
    307   1.1  christos 		{
    308  1.10  christos 		  invalid = true;
    309   1.6  christos 		  break;
    310   1.1  christos 		}
    311   1.1  christos 	    }
    312   1.1  christos 
    313   1.6  christos 	  if (operand->flags & ARC_OPERAND_LIMM
    314   1.6  christos 	      && !(operand->flags & ARC_OPERAND_DUPLICATE))
    315  1.10  christos 	    *has_limm = true;
    316   1.6  christos 	}
    317   1.6  christos 
    318   1.6  christos       /* Check the flags.  */
    319   1.6  christos       for (flgidx = opcode->flags; *flgidx; flgidx++)
    320   1.6  christos 	{
    321   1.6  christos 	  /* Get a valid flag class.  */
    322   1.6  christos 	  const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
    323   1.6  christos 	  const unsigned *flgopridx;
    324   1.6  christos 	  int foundA = 0, foundB = 0;
    325   1.6  christos 	  unsigned int value;
    326   1.6  christos 
    327   1.6  christos 	  /* Check first the extensions.  */
    328   1.6  christos 	  if (cl_flags->flag_class & F_CLASS_EXTEND)
    329   1.1  christos 	    {
    330   1.7  christos 	      value = (insn & 0x1F);
    331   1.6  christos 	      if (arcExtMap_condCodeName (value))
    332   1.6  christos 		continue;
    333   1.6  christos 	    }
    334   1.1  christos 
    335   1.7  christos 	  /* Check for the implicit flags.  */
    336   1.7  christos 	  if (cl_flags->flag_class & F_CLASS_IMPLICIT)
    337   1.7  christos 	    continue;
    338   1.7  christos 
    339   1.6  christos 	  for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
    340   1.1  christos 	    {
    341   1.6  christos 	      const struct arc_flag_operand *flg_operand =
    342   1.6  christos 		&arc_flag_operands[*flgopridx];
    343   1.1  christos 
    344   1.7  christos 	      value = (insn >> flg_operand->shift)
    345   1.6  christos 		& ((1 << flg_operand->bits) - 1);
    346   1.6  christos 	      if (value == flg_operand->code)
    347   1.6  christos 		foundA = 1;
    348   1.6  christos 	      if (value)
    349   1.6  christos 		foundB = 1;
    350   1.1  christos 	    }
    351   1.6  christos 
    352   1.6  christos 	  if (!foundA && foundB)
    353   1.1  christos 	    {
    354  1.10  christos 	      invalid = true;
    355   1.6  christos 	      break;
    356   1.6  christos 	    }
    357   1.6  christos 	}
    358   1.6  christos 
    359   1.6  christos       if (invalid)
    360   1.6  christos 	continue;
    361   1.6  christos 
    362   1.6  christos       if (insn_len == 4
    363   1.7  christos 	  && overlaps)
    364   1.7  christos 	{
    365  1.10  christos 	  warn_p = true;
    366   1.7  christos 	  t_op = opcode;
    367   1.7  christos 	  if (skip_this_opcode (opcode))
    368   1.7  christos 	    continue;
    369   1.7  christos 	}
    370   1.6  christos 
    371   1.6  christos       /* The instruction is valid.  */
    372   1.6  christos       return opcode;
    373   1.6  christos     }
    374   1.6  christos   while (opcode->mask);
    375   1.6  christos 
    376   1.7  christos   if (warn_p)
    377   1.6  christos     {
    378  1.10  christos       info->fprintf_styled_func
    379  1.10  christos 	(info->stream, dis_style_text,
    380  1.10  christos 	 _("\nWarning: disassembly may be wrong due to "
    381  1.10  christos 	   "guessed opcode class choice.\n"
    382  1.10  christos 	   "Use -M<class[,class]> to select the correct "
    383  1.10  christos 	   "opcode class(es).\n\t\t\t\t"));
    384   1.7  christos       return t_op;
    385   1.6  christos     }
    386   1.6  christos 
    387   1.6  christos   return NULL;
    388   1.6  christos }
    389   1.6  christos 
    390   1.6  christos /* Find opcode for INSN, trying various different sources.  The instruction
    391   1.6  christos    length in INSN_LEN will be updated if the instruction requires a LIMM
    392   1.7  christos    extension.
    393   1.6  christos 
    394   1.6  christos    A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
    395   1.7  christos    initialised, ready to iterate over the operands of the found opcode.  If
    396   1.7  christos    the found opcode requires a LIMM then the LIMM value will be loaded into a
    397   1.7  christos    field of ITER.
    398   1.6  christos 
    399   1.6  christos    This function returns TRUE in almost all cases, FALSE is reserved to
    400   1.7  christos    indicate an error (failing to find an opcode is not an error) a returned
    401   1.7  christos    result of FALSE would indicate that the disassembler can't continue.
    402   1.7  christos 
    403   1.7  christos    If no matching opcode is found then the returned result will be TRUE, the
    404   1.7  christos    value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
    405   1.7  christos    INSN_LEN will be unchanged.
    406   1.7  christos 
    407   1.7  christos    If a matching opcode is found, then the returned result will be TRUE, the
    408   1.7  christos    opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
    409   1.7  christos    4 if the instruction requires a LIMM, and the LIMM value will have been
    410   1.7  christos    loaded into a field of ITER.  Finally, ITER will have been initialised so
    411   1.7  christos    that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
    412   1.7  christos    operands.  */
    413   1.6  christos 
    414  1.10  christos static bool
    415   1.6  christos find_format (bfd_vma                       memaddr,
    416   1.7  christos 	     unsigned long long            insn,
    417   1.6  christos 	     unsigned int *                insn_len,
    418   1.6  christos              unsigned                      isa_mask,
    419   1.6  christos 	     struct disassemble_info *     info,
    420   1.6  christos              const struct arc_opcode **    opcode_result,
    421   1.6  christos              struct arc_operand_iterator * iter)
    422   1.6  christos {
    423   1.6  christos   const struct arc_opcode *opcode = NULL;
    424  1.10  christos   bool needs_limm = false;
    425   1.7  christos   const extInstruction_t *einsn, *i;
    426   1.7  christos   unsigned limm = 0;
    427   1.7  christos   struct arc_disassemble_info *arc_infop = info->private_data;
    428   1.6  christos 
    429   1.6  christos   /* First, try the extension instructions.  */
    430   1.7  christos   if (*insn_len == 4)
    431   1.6  christos     {
    432   1.7  christos       einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
    433   1.7  christos       for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next)
    434   1.7  christos 	{
    435   1.7  christos 	  const char *errmsg = NULL;
    436   1.1  christos 
    437   1.7  christos 	  opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg);
    438   1.7  christos 	  if (opcode == NULL)
    439   1.7  christos 	    {
    440  1.10  christos 	      (*info->fprintf_styled_func)
    441  1.10  christos 		(info->stream, dis_style_text,
    442  1.10  christos 		 _("An error occurred while generating "
    443  1.10  christos 		   "the extension instruction operations"));
    444   1.7  christos 	      *opcode_result = NULL;
    445  1.10  christos 	      return false;
    446   1.7  christos 	    }
    447   1.7  christos 
    448   1.7  christos 	  opcode = find_format_from_table (info, opcode, insn, *insn_len,
    449  1.10  christos 					   isa_mask, &needs_limm, false);
    450   1.6  christos 	}
    451   1.6  christos     }
    452   1.1  christos 
    453   1.6  christos   /* Then, try finding the first match in the opcode table.  */
    454   1.6  christos   if (opcode == NULL)
    455   1.6  christos     opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
    456  1.10  christos 				     isa_mask, &needs_limm, true);
    457   1.1  christos 
    458   1.9  christos   if (opcode != NULL && needs_limm)
    459   1.6  christos     {
    460   1.6  christos       bfd_byte buffer[4];
    461   1.6  christos       int status;
    462   1.1  christos 
    463   1.6  christos       status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
    464   1.6  christos                                           4, info);
    465   1.6  christos       if (status != 0)
    466   1.6  christos         {
    467   1.6  christos           opcode = NULL;
    468   1.6  christos         }
    469   1.6  christos       else
    470   1.6  christos         {
    471   1.7  christos           limm = ARRANGE_ENDIAN (info, buffer);
    472   1.6  christos           *insn_len += 4;
    473   1.6  christos         }
    474   1.6  christos     }
    475   1.1  christos 
    476   1.7  christos   if (opcode != NULL)
    477   1.6  christos     {
    478   1.6  christos       iter->insn = insn;
    479   1.7  christos       iter->limm = limm;
    480   1.7  christos       iter->opcode = opcode;
    481   1.7  christos       iter->opidx = opcode->operands;
    482   1.6  christos     }
    483   1.1  christos 
    484   1.6  christos   *opcode_result = opcode;
    485   1.7  christos 
    486   1.7  christos   /* Update private data.  */
    487   1.7  christos   arc_infop->opcode = opcode;
    488   1.9  christos   arc_infop->limm = limm;
    489   1.7  christos   arc_infop->limm_p = needs_limm;
    490   1.7  christos 
    491  1.10  christos   return true;
    492   1.1  christos }
    493   1.1  christos 
    494   1.1  christos static void
    495   1.6  christos print_flags (const struct arc_opcode *opcode,
    496   1.7  christos 	     unsigned long long *insn,
    497   1.6  christos 	     struct disassemble_info *info)
    498   1.1  christos {
    499   1.6  christos   const unsigned char *flgidx;
    500   1.6  christos   unsigned int value;
    501   1.7  christos   struct arc_disassemble_info *arc_infop = info->private_data;
    502   1.6  christos 
    503   1.6  christos   /* Now extract and print the flags.  */
    504   1.6  christos   for (flgidx = opcode->flags; *flgidx; flgidx++)
    505   1.1  christos     {
    506   1.6  christos       /* Get a valid flag class.  */
    507   1.6  christos       const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
    508   1.6  christos       const unsigned *flgopridx;
    509   1.1  christos 
    510   1.6  christos       /* Check first the extensions.  */
    511   1.6  christos       if (cl_flags->flag_class & F_CLASS_EXTEND)
    512   1.1  christos 	{
    513   1.6  christos 	  const char *name;
    514   1.6  christos 	  value = (insn[0] & 0x1F);
    515   1.1  christos 
    516   1.6  christos 	  name = arcExtMap_condCodeName (value);
    517   1.6  christos 	  if (name)
    518   1.6  christos 	    {
    519  1.10  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
    520  1.10  christos 					    ".%s", name);
    521   1.6  christos 	      continue;
    522   1.6  christos 	    }
    523   1.1  christos 	}
    524   1.6  christos 
    525   1.6  christos       for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
    526   1.1  christos 	{
    527   1.6  christos 	  const struct arc_flag_operand *flg_operand =
    528   1.6  christos 	    &arc_flag_operands[*flgopridx];
    529   1.6  christos 
    530   1.7  christos 	  /* Implicit flags are only used for the insn decoder.  */
    531   1.7  christos 	  if (cl_flags->flag_class & F_CLASS_IMPLICIT)
    532   1.7  christos 	    {
    533   1.7  christos 	      if (cl_flags->flag_class & F_CLASS_COND)
    534   1.7  christos 		arc_infop->condition_code = flg_operand->code;
    535   1.7  christos 	      else if (cl_flags->flag_class & F_CLASS_WB)
    536   1.7  christos 		arc_infop->writeback_mode = flg_operand->code;
    537   1.7  christos 	      else if (cl_flags->flag_class & F_CLASS_ZZ)
    538   1.7  christos 		info->data_size = flg_operand->code;
    539   1.7  christos 	      continue;
    540   1.7  christos 	    }
    541   1.7  christos 
    542   1.6  christos 	  if (!flg_operand->favail)
    543   1.6  christos 	    continue;
    544   1.6  christos 
    545   1.6  christos 	  value = (insn[0] >> flg_operand->shift)
    546   1.6  christos 	    & ((1 << flg_operand->bits) - 1);
    547   1.6  christos 	  if (value == flg_operand->code)
    548   1.6  christos 	    {
    549   1.6  christos 	       /* FIXME!: print correctly nt/t flag.  */
    550   1.6  christos 	      if (!special_flag_p (opcode->name, flg_operand->name))
    551  1.10  christos 		(*info->fprintf_styled_func) (info->stream,
    552  1.10  christos 					      dis_style_mnemonic, ".");
    553   1.6  christos 	      else if (info->insn_type == dis_dref)
    554   1.6  christos 		{
    555   1.6  christos 		  switch (flg_operand->name[0])
    556   1.6  christos 		    {
    557   1.6  christos 		    case 'b':
    558   1.6  christos 		      info->data_size = 1;
    559   1.6  christos 		      break;
    560   1.6  christos 		    case 'h':
    561   1.6  christos 		    case 'w':
    562   1.6  christos 		      info->data_size = 2;
    563   1.6  christos 		      break;
    564   1.6  christos 		    default:
    565   1.6  christos 		      info->data_size = 4;
    566   1.6  christos 		      break;
    567   1.6  christos 		    }
    568   1.6  christos 		}
    569   1.6  christos 	      if (flg_operand->name[0] == 'd'
    570   1.6  christos 		  && flg_operand->name[1] == 0)
    571   1.6  christos 		info->branch_delay_insns = 1;
    572   1.6  christos 
    573   1.6  christos 	      /* Check if it is a conditional flag.  */
    574   1.6  christos 	      if (cl_flags->flag_class & F_CLASS_COND)
    575   1.6  christos 		{
    576   1.6  christos 		  if (info->insn_type == dis_jsr)
    577   1.6  christos 		    info->insn_type = dis_condjsr;
    578   1.6  christos 		  else if (info->insn_type == dis_branch)
    579   1.6  christos 		    info->insn_type = dis_condbranch;
    580   1.7  christos 		  arc_infop->condition_code = flg_operand->code;
    581   1.6  christos 		}
    582   1.6  christos 
    583   1.7  christos 	      /* Check for the write back modes.  */
    584   1.7  christos 	      if (cl_flags->flag_class & F_CLASS_WB)
    585   1.7  christos 		arc_infop->writeback_mode = flg_operand->code;
    586   1.7  christos 
    587  1.10  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
    588  1.10  christos 					    "%s", flg_operand->name);
    589   1.6  christos 	    }
    590   1.1  christos 	}
    591   1.1  christos     }
    592   1.1  christos }
    593   1.1  christos 
    594   1.6  christos static const char *
    595   1.6  christos get_auxreg (const struct arc_opcode *opcode,
    596   1.6  christos 	    int value,
    597   1.6  christos 	    unsigned isa_mask)
    598   1.6  christos {
    599   1.6  christos   const char *name;
    600   1.6  christos   unsigned int i;
    601   1.6  christos   const struct arc_aux_reg *auxr = &arc_aux_regs[0];
    602   1.6  christos 
    603   1.6  christos   if (opcode->insn_class != AUXREG)
    604   1.6  christos     return NULL;
    605   1.6  christos 
    606   1.6  christos   name = arcExtMap_auxRegName (value);
    607   1.6  christos   if (name)
    608   1.6  christos     return name;
    609   1.6  christos 
    610   1.6  christos   for (i = 0; i < arc_num_aux_regs; i++, auxr++)
    611   1.6  christos     {
    612   1.6  christos       if (!(auxr->cpu & isa_mask))
    613   1.6  christos 	continue;
    614   1.6  christos 
    615   1.6  christos       if (auxr->subclass != NONE)
    616   1.6  christos 	return NULL;
    617   1.1  christos 
    618   1.6  christos       if (auxr->address == value)
    619   1.6  christos 	return auxr->name;
    620   1.6  christos     }
    621   1.6  christos   return NULL;
    622   1.6  christos }
    623   1.6  christos 
    624   1.6  christos /* Convert a value representing an address type to a string used to refer to
    625   1.6  christos    the address type in assembly code.  */
    626   1.6  christos 
    627   1.6  christos static const char *
    628   1.6  christos get_addrtype (int value)
    629   1.1  christos {
    630   1.6  christos   if (value < 0 || value > addrtypenames_max)
    631   1.6  christos     return addrtypeunknown;
    632   1.6  christos 
    633   1.6  christos   return addrtypenames[value];
    634   1.6  christos }
    635   1.6  christos 
    636   1.6  christos /* Calculate the instruction length for an instruction starting with MSB
    637   1.6  christos    and LSB, the most and least significant byte.  The ISA_MASK is used to
    638   1.6  christos    filter the instructions considered to only those that are part of the
    639   1.6  christos    current architecture.
    640   1.6  christos 
    641   1.6  christos    The instruction lengths are calculated from the ARC_OPCODE table, and
    642   1.6  christos    cached for later use.  */
    643   1.6  christos 
    644   1.6  christos static unsigned int
    645   1.6  christos arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
    646   1.6  christos {
    647   1.6  christos   bfd_byte major_opcode = msb >> 3;
    648   1.1  christos 
    649   1.6  christos   switch (info->mach)
    650   1.1  christos     {
    651   1.6  christos     case bfd_mach_arc_arc700:
    652   1.6  christos       /* The nps400 extension set requires this special casing of the
    653   1.6  christos 	 instruction length calculation.  Right now this is not causing any
    654   1.6  christos 	 problems as none of the known extensions overlap in opcode space,
    655   1.6  christos 	 but, if they ever do then we might need to start carrying
    656   1.6  christos 	 information around in the elf about which extensions are in use.  */
    657   1.6  christos       if (major_opcode == 0xb)
    658   1.6  christos         {
    659   1.6  christos           bfd_byte minor_opcode = lsb & 0x1f;
    660   1.6  christos 
    661   1.7  christos 	  if (minor_opcode < 4)
    662   1.7  christos 	    return 6;
    663   1.7  christos 	  else if (minor_opcode == 0x10 || minor_opcode == 0x11)
    664   1.7  christos 	    return 8;
    665   1.6  christos         }
    666   1.7  christos       if (major_opcode == 0xa)
    667   1.7  christos         {
    668   1.7  christos           return 8;
    669   1.7  christos         }
    670   1.7  christos       /* Fall through.  */
    671   1.6  christos     case bfd_mach_arc_arc600:
    672   1.6  christos       return (major_opcode > 0xb) ? 2 : 4;
    673   1.6  christos       break;
    674   1.6  christos 
    675   1.6  christos     case bfd_mach_arc_arcv2:
    676   1.6  christos       return (major_opcode > 0x7) ? 2 : 4;
    677   1.6  christos       break;
    678   1.6  christos 
    679   1.6  christos     default:
    680   1.9  christos       return 0;
    681   1.6  christos     }
    682   1.6  christos }
    683   1.6  christos 
    684   1.6  christos /* Extract and return the value of OPERAND from the instruction whose value
    685   1.6  christos    is held in the array INSN.  */
    686   1.1  christos 
    687   1.6  christos static int
    688   1.7  christos extract_operand_value (const struct arc_operand *operand,
    689   1.7  christos 		       unsigned long long insn,
    690   1.7  christos 		       unsigned limm)
    691   1.6  christos {
    692   1.6  christos   int value;
    693   1.1  christos 
    694   1.6  christos   /* Read the limm operand, if required.  */
    695   1.6  christos   if (operand->flags & ARC_OPERAND_LIMM)
    696   1.6  christos     /* The second part of the instruction value will have been loaded as
    697   1.6  christos        part of the find_format call made earlier.  */
    698   1.7  christos     value = limm;
    699   1.6  christos   else
    700   1.6  christos     {
    701   1.6  christos       if (operand->extract)
    702  1.10  christos 	value = (*operand->extract) (insn, (bool *) NULL);
    703   1.1  christos       else
    704   1.6  christos         {
    705   1.6  christos           if (operand->flags & ARC_OPERAND_ALIGNED32)
    706   1.6  christos             {
    707   1.7  christos               value = (insn >> operand->shift)
    708   1.6  christos                 & ((1 << (operand->bits - 2)) - 1);
    709   1.6  christos               value = value << 2;
    710   1.6  christos             }
    711   1.6  christos           else
    712   1.6  christos             {
    713   1.7  christos               value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
    714   1.6  christos             }
    715   1.6  christos           if (operand->flags & ARC_OPERAND_SIGNED)
    716   1.6  christos             {
    717   1.6  christos               int signbit = 1 << (operand->bits - 1);
    718   1.6  christos               value = (value ^ signbit) - signbit;
    719   1.6  christos             }
    720   1.6  christos         }
    721   1.6  christos     }
    722   1.6  christos 
    723   1.6  christos   return value;
    724   1.6  christos }
    725   1.6  christos 
    726   1.6  christos /* Find the next operand, and the operands value from ITER.  Return TRUE if
    727   1.6  christos    there is another operand, otherwise return FALSE.  If there is an
    728   1.6  christos    operand returned then the operand is placed into OPERAND, and the value
    729   1.6  christos    into VALUE.  If there is no operand returned then OPERAND and VALUE are
    730   1.6  christos    unchanged.  */
    731   1.6  christos 
    732  1.10  christos static bool
    733   1.6  christos operand_iterator_next (struct arc_operand_iterator *iter,
    734   1.6  christos                        const struct arc_operand **operand,
    735   1.6  christos                        int *value)
    736   1.6  christos {
    737   1.7  christos   if (*iter->opidx == 0)
    738   1.6  christos     {
    739   1.7  christos       *operand = NULL;
    740  1.10  christos       return false;
    741   1.6  christos     }
    742   1.1  christos 
    743   1.7  christos   *operand = &arc_operands[*iter->opidx];
    744   1.7  christos   *value = extract_operand_value (*operand, iter->insn, iter->limm);
    745   1.7  christos   iter->opidx++;
    746   1.6  christos 
    747  1.10  christos   return true;
    748   1.6  christos }
    749   1.6  christos 
    750   1.6  christos /* Helper for parsing the options.  */
    751   1.6  christos 
    752   1.6  christos static void
    753   1.7  christos parse_option (const char *option)
    754   1.6  christos {
    755   1.8  christos   if (disassembler_options_cmp (option, "dsp") == 0)
    756   1.6  christos     add_to_decodelist (DSP, NONE);
    757   1.6  christos 
    758   1.8  christos   else if (disassembler_options_cmp (option, "spfp") == 0)
    759   1.6  christos     add_to_decodelist (FLOAT, SPX);
    760   1.1  christos 
    761   1.8  christos   else if (disassembler_options_cmp (option, "dpfp") == 0)
    762   1.6  christos     add_to_decodelist (FLOAT, DPX);
    763   1.1  christos 
    764   1.8  christos   else if (disassembler_options_cmp (option, "quarkse_em") == 0)
    765   1.7  christos     {
    766   1.7  christos       add_to_decodelist (FLOAT, DPX);
    767   1.7  christos       add_to_decodelist (FLOAT, SPX);
    768   1.8  christos       add_to_decodelist (FLOAT, QUARKSE1);
    769   1.8  christos       add_to_decodelist (FLOAT, QUARKSE2);
    770   1.7  christos     }
    771   1.6  christos 
    772   1.8  christos   else if (disassembler_options_cmp (option, "fpuda") == 0)
    773   1.6  christos     add_to_decodelist (FLOAT, DPA);
    774   1.6  christos 
    775   1.9  christos   else if (disassembler_options_cmp (option, "nps400") == 0)
    776   1.9  christos     {
    777   1.9  christos       add_to_decodelist (ACL, NPS400);
    778   1.9  christos       add_to_decodelist (ARITH, NPS400);
    779   1.9  christos       add_to_decodelist (BITOP, NPS400);
    780   1.9  christos       add_to_decodelist (BMU, NPS400);
    781   1.9  christos       add_to_decodelist (CONTROL, NPS400);
    782   1.9  christos       add_to_decodelist (DMA, NPS400);
    783   1.9  christos       add_to_decodelist (DPI, NPS400);
    784   1.9  christos       add_to_decodelist (MEMORY, NPS400);
    785   1.9  christos       add_to_decodelist (MISC, NPS400);
    786   1.9  christos       add_to_decodelist (NET, NPS400);
    787   1.9  christos       add_to_decodelist (PMU, NPS400);
    788   1.9  christos       add_to_decodelist (PROTOCOL_DECODE, NPS400);
    789   1.9  christos       add_to_decodelist (ULTRAIP, NPS400);
    790   1.9  christos     }
    791   1.9  christos 
    792   1.8  christos   else if (disassembler_options_cmp (option, "fpus") == 0)
    793   1.1  christos     {
    794   1.6  christos       add_to_decodelist (FLOAT, SP);
    795   1.6  christos       add_to_decodelist (FLOAT, CVT);
    796   1.1  christos     }
    797   1.1  christos 
    798   1.8  christos   else if (disassembler_options_cmp (option, "fpud") == 0)
    799   1.6  christos     {
    800   1.6  christos       add_to_decodelist (FLOAT, DP);
    801   1.6  christos       add_to_decodelist (FLOAT, CVT);
    802   1.6  christos     }
    803  1.10  christos   else if (startswith (option, "hex"))
    804  1.10  christos     print_hex = true;
    805   1.6  christos   else
    806   1.8  christos     /* xgettext:c-format */
    807   1.8  christos     opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
    808   1.8  christos }
    809   1.8  christos 
    810   1.8  christos #define ARC_CPU_TYPE_A6xx(NAME,EXTRA)			\
    811   1.8  christos   { #NAME, ARC_OPCODE_ARC600, "ARC600" }
    812   1.8  christos #define ARC_CPU_TYPE_A7xx(NAME,EXTRA)			\
    813   1.8  christos   { #NAME, ARC_OPCODE_ARC700, "ARC700" }
    814   1.8  christos #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA)			\
    815   1.8  christos   { #NAME,  ARC_OPCODE_ARCv2EM, "ARC EM" }
    816   1.8  christos #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA)			\
    817   1.8  christos   { #NAME,  ARC_OPCODE_ARCv2HS, "ARC HS" }
    818   1.8  christos #define ARC_CPU_TYPE_NONE				\
    819   1.8  christos   { 0, 0, 0 }
    820   1.8  christos 
    821   1.8  christos /* A table of CPU names and opcode sets.  */
    822   1.8  christos static const struct cpu_type
    823   1.8  christos {
    824   1.8  christos   const char *name;
    825   1.8  christos   unsigned flags;
    826   1.8  christos   const char *isa;
    827   1.8  christos }
    828   1.8  christos   cpu_types[] =
    829   1.8  christos {
    830   1.8  christos   #include "elf/arc-cpu.def"
    831   1.8  christos };
    832   1.8  christos 
    833   1.8  christos /* Helper for parsing the CPU options.  Accept any of the ARC architectures
    834   1.8  christos    values.  OPTION should be a value passed to cpu=.  */
    835   1.8  christos 
    836   1.8  christos static unsigned
    837   1.8  christos parse_cpu_option (const char *option)
    838   1.8  christos {
    839   1.8  christos   int i;
    840   1.8  christos 
    841   1.8  christos   for (i = 0; cpu_types[i].name; ++i)
    842   1.8  christos     {
    843   1.8  christos       if (!disassembler_options_cmp (cpu_types[i].name, option))
    844   1.8  christos 	{
    845   1.8  christos 	  return cpu_types[i].flags;
    846   1.8  christos 	}
    847   1.8  christos     }
    848   1.8  christos 
    849   1.8  christos   /* xgettext:c-format */
    850   1.8  christos   opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
    851   1.8  christos   return ARC_OPCODE_NONE;
    852   1.6  christos }
    853   1.1  christos 
    854   1.6  christos /* Go over the options list and parse it.  */
    855   1.1  christos 
    856   1.6  christos static void
    857   1.7  christos parse_disassembler_options (const char *options)
    858   1.6  christos {
    859   1.8  christos   const char *option;
    860   1.8  christos 
    861   1.6  christos   if (options == NULL)
    862   1.6  christos     return;
    863   1.6  christos 
    864   1.8  christos   /* Disassembler might be reused for difference CPU's, and cpu option set for
    865   1.8  christos      the first one shouldn't be applied to second (which might not have
    866   1.8  christos      explicit cpu in its options.  Therefore it is required to reset enforced
    867   1.8  christos      CPU when new options are being parsed.  */
    868   1.8  christos   enforced_isa_mask = ARC_OPCODE_NONE;
    869   1.8  christos 
    870   1.8  christos   FOR_EACH_DISASSEMBLER_OPTION (option, options)
    871   1.8  christos     {
    872   1.8  christos       /* A CPU option?  Cannot use STRING_COMMA_LEN because strncmp is also a
    873   1.8  christos 	 preprocessor macro.  */
    874   1.8  christos       if (strncmp (option, "cpu=", 4) == 0)
    875   1.8  christos 	/* Strip leading `cpu=`.  */
    876   1.8  christos 	enforced_isa_mask = parse_cpu_option (option + 4);
    877   1.8  christos       else
    878   1.8  christos 	parse_option (option);
    879   1.6  christos     }
    880   1.1  christos }
    881   1.1  christos 
    882   1.7  christos /* Return the instruction type for an instruction described by OPCODE.  */
    883   1.7  christos 
    884   1.7  christos static enum dis_insn_type
    885   1.7  christos arc_opcode_to_insn_type (const struct arc_opcode *opcode)
    886   1.7  christos {
    887   1.7  christos   enum dis_insn_type insn_type;
    888   1.7  christos 
    889   1.7  christos   switch (opcode->insn_class)
    890   1.7  christos     {
    891   1.7  christos     case BRANCH:
    892   1.7  christos     case BBIT0:
    893   1.7  christos     case BBIT1:
    894   1.7  christos     case BI:
    895   1.7  christos     case BIH:
    896   1.7  christos     case BRCC:
    897  1.11  christos     case DBNZ:
    898   1.7  christos     case EI:
    899   1.7  christos     case JLI:
    900   1.7  christos     case JUMP:
    901   1.7  christos     case LOOP:
    902   1.7  christos       if (!strncmp (opcode->name, "bl", 2)
    903   1.7  christos 	  || !strncmp (opcode->name, "jl", 2))
    904   1.7  christos 	{
    905   1.7  christos 	  if (opcode->subclass == COND)
    906   1.7  christos 	    insn_type = dis_condjsr;
    907   1.7  christos 	  else
    908   1.7  christos 	    insn_type = dis_jsr;
    909   1.7  christos 	}
    910   1.7  christos       else
    911   1.7  christos 	{
    912   1.7  christos 	  if (opcode->subclass == COND)
    913   1.7  christos 	    insn_type = dis_condbranch;
    914   1.7  christos 	  else
    915   1.7  christos 	    insn_type = dis_branch;
    916   1.7  christos 	}
    917   1.7  christos       break;
    918   1.7  christos     case LOAD:
    919   1.7  christos     case STORE:
    920   1.7  christos     case MEMORY:
    921   1.7  christos     case ENTER:
    922   1.7  christos     case PUSH:
    923   1.7  christos     case POP:
    924   1.7  christos       insn_type = dis_dref;
    925   1.7  christos       break;
    926   1.7  christos     case LEAVE:
    927   1.7  christos       insn_type = dis_branch;
    928   1.7  christos       break;
    929   1.7  christos     default:
    930   1.7  christos       insn_type = dis_nonbranch;
    931   1.7  christos       break;
    932   1.7  christos     }
    933   1.7  christos 
    934   1.7  christos   return insn_type;
    935   1.7  christos }
    936   1.7  christos 
    937   1.6  christos /* Disassemble ARC instructions.  */
    938   1.1  christos 
    939   1.1  christos static int
    940   1.6  christos print_insn_arc (bfd_vma memaddr,
    941   1.6  christos 		struct disassemble_info *info)
    942   1.1  christos {
    943   1.7  christos   bfd_byte buffer[8];
    944   1.7  christos   unsigned int highbyte, lowbyte;
    945   1.6  christos   int status;
    946   1.6  christos   unsigned int insn_len;
    947   1.7  christos   unsigned long long insn = 0;
    948   1.8  christos   unsigned isa_mask = ARC_OPCODE_NONE;
    949   1.6  christos   const struct arc_opcode *opcode;
    950  1.10  christos   bool need_comma;
    951  1.10  christos   bool open_braket;
    952   1.6  christos   int size;
    953   1.6  christos   const struct arc_operand *operand;
    954   1.8  christos   int value, vpcl;
    955   1.6  christos   struct arc_operand_iterator iter;
    956   1.7  christos   struct arc_disassemble_info *arc_infop;
    957  1.10  christos   bool rpcl = false, rset = false;
    958   1.6  christos 
    959   1.6  christos   if (info->disassembler_options)
    960   1.6  christos     {
    961   1.6  christos       parse_disassembler_options (info->disassembler_options);
    962   1.6  christos 
    963   1.6  christos       /* Avoid repeated parsing of the options.  */
    964   1.6  christos       info->disassembler_options = NULL;
    965   1.6  christos     }
    966   1.6  christos 
    967   1.7  christos   if (info->private_data == NULL && !init_arc_disasm_info (info))
    968   1.7  christos     return -1;
    969   1.7  christos 
    970   1.6  christos   memset (&iter, 0, sizeof (iter));
    971   1.7  christos   highbyte  = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
    972   1.7  christos   lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
    973   1.6  christos 
    974   1.8  christos   /* Figure out CPU type, unless it was enforced via disassembler options.  */
    975   1.8  christos   if (enforced_isa_mask == ARC_OPCODE_NONE)
    976   1.8  christos     {
    977   1.8  christos       Elf_Internal_Ehdr *header = NULL;
    978   1.8  christos 
    979   1.8  christos       if (info->section && info->section->owner)
    980   1.8  christos 	header = elf_elfheader (info->section->owner);
    981   1.6  christos 
    982   1.8  christos       switch (info->mach)
    983   1.8  christos 	{
    984   1.8  christos 	case bfd_mach_arc_arc700:
    985   1.8  christos 	  isa_mask = ARC_OPCODE_ARC700;
    986   1.8  christos 	  break;
    987   1.1  christos 
    988   1.8  christos 	case bfd_mach_arc_arc600:
    989   1.8  christos 	  isa_mask = ARC_OPCODE_ARC600;
    990   1.8  christos 	  break;
    991   1.1  christos 
    992   1.8  christos 	case bfd_mach_arc_arcv2:
    993   1.8  christos 	default:
    994   1.8  christos 	  isa_mask = ARC_OPCODE_ARCv2EM;
    995   1.8  christos 	  /* TODO: Perhaps remove definition of header since it is only used at
    996   1.8  christos 	     this location.  */
    997   1.8  christos 	  if (header != NULL
    998   1.8  christos 	      && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
    999   1.8  christos 	    isa_mask = ARC_OPCODE_ARCv2HS;
   1000   1.8  christos 	  break;
   1001   1.1  christos 	}
   1002   1.8  christos     }
   1003   1.8  christos   else
   1004   1.8  christos     isa_mask = enforced_isa_mask;
   1005   1.8  christos 
   1006   1.8  christos   if (isa_mask == ARC_OPCODE_ARCv2HS)
   1007   1.8  christos     {
   1008   1.8  christos       /* FPU instructions are not extensions for HS.  */
   1009   1.8  christos       add_to_decodelist (FLOAT, SP);
   1010   1.8  christos       add_to_decodelist (FLOAT, DP);
   1011   1.8  christos       add_to_decodelist (FLOAT, CVT);
   1012   1.6  christos     }
   1013   1.1  christos 
   1014   1.6  christos   /* This variable may be set by the instruction decoder.  It suggests
   1015   1.6  christos      the number of bytes objdump should display on a single line.  If
   1016   1.6  christos      the instruction decoder sets this, it should always set it to
   1017   1.6  christos      the same value in order to get reasonable looking output.  */
   1018   1.6  christos   info->bytes_per_line  = 8;
   1019   1.6  christos 
   1020   1.6  christos   /* In the next lines, we set two info variables control the way
   1021   1.6  christos      objdump displays the raw data.  For example, if bytes_per_line is
   1022   1.6  christos      8 and bytes_per_chunk is 4, the output will look like this:
   1023   1.6  christos      00:   00000000 00000000
   1024   1.6  christos      with the chunks displayed according to "display_endian".  */
   1025   1.6  christos   if (info->section
   1026   1.6  christos       && !(info->section->flags & SEC_CODE))
   1027   1.6  christos     {
   1028   1.6  christos       /* This is not a CODE section.  */
   1029   1.6  christos       switch (info->section->size)
   1030   1.6  christos 	{
   1031   1.6  christos 	case 1:
   1032   1.6  christos 	case 2:
   1033   1.6  christos 	case 4:
   1034   1.6  christos 	  size = info->section->size;
   1035   1.1  christos 	  break;
   1036   1.1  christos 	default:
   1037   1.6  christos 	  size = (info->section->size & 0x01) ? 1 : 4;
   1038   1.1  christos 	  break;
   1039   1.1  christos 	}
   1040   1.6  christos       info->bytes_per_chunk = 1;
   1041   1.6  christos       info->display_endian = info->endian;
   1042   1.6  christos     }
   1043   1.6  christos   else
   1044   1.6  christos     {
   1045   1.6  christos       size = 2;
   1046   1.6  christos       info->bytes_per_chunk = 2;
   1047   1.6  christos       info->display_endian = info->endian;
   1048   1.6  christos     }
   1049   1.1  christos 
   1050   1.6  christos   /* Read the insn into a host word.  */
   1051   1.6  christos   status = (*info->read_memory_func) (memaddr, buffer, size, info);
   1052   1.8  christos 
   1053   1.6  christos   if (status != 0)
   1054   1.6  christos     {
   1055   1.6  christos       (*info->memory_error_func) (status, memaddr, info);
   1056   1.6  christos       return -1;
   1057   1.6  christos     }
   1058   1.1  christos 
   1059   1.6  christos   if (info->section
   1060   1.6  christos       && !(info->section->flags & SEC_CODE))
   1061   1.6  christos     {
   1062   1.6  christos       /* Data section.  */
   1063   1.6  christos       unsigned long data;
   1064   1.1  christos 
   1065   1.6  christos       data = bfd_get_bits (buffer, size * 8,
   1066   1.6  christos 			   info->display_endian == BFD_ENDIAN_BIG);
   1067   1.6  christos       switch (size)
   1068   1.1  christos 	{
   1069   1.6  christos 	case 1:
   1070  1.10  christos 	  (*info->fprintf_styled_func) (info->stream,
   1071  1.10  christos 					dis_style_assembler_directive,
   1072  1.10  christos 					".byte");
   1073  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
   1074  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1075  1.10  christos 					"0x%02lx", data);
   1076   1.1  christos 	  break;
   1077   1.6  christos 	case 2:
   1078  1.10  christos 	  (*info->fprintf_styled_func) (info->stream,
   1079  1.10  christos 					dis_style_assembler_directive,
   1080  1.10  christos 					".short");
   1081  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
   1082  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1083  1.10  christos 					"0x%04lx", data);
   1084   1.1  christos 	  break;
   1085   1.6  christos 	case 4:
   1086  1.10  christos 	  (*info->fprintf_styled_func) (info->stream,
   1087  1.10  christos 					dis_style_assembler_directive,
   1088  1.10  christos 					".word");
   1089  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
   1090  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1091  1.10  christos 					"0x%08lx", data);
   1092   1.1  christos 	  break;
   1093   1.6  christos 	default:
   1094   1.9  christos 	  return -1;
   1095   1.1  christos 	}
   1096   1.6  christos       return size;
   1097   1.6  christos     }
   1098   1.1  christos 
   1099   1.7  christos   insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
   1100   1.6  christos   pr_debug ("instruction length = %d bytes\n", insn_len);
   1101   1.9  christos   if (insn_len == 0)
   1102   1.9  christos     return -1;
   1103   1.9  christos 
   1104   1.7  christos   arc_infop = info->private_data;
   1105   1.7  christos   arc_infop->insn_len = insn_len;
   1106   1.1  christos 
   1107   1.6  christos   switch (insn_len)
   1108   1.6  christos     {
   1109   1.6  christos     case 2:
   1110   1.7  christos       insn = (buffer[highbyte] << 8) | buffer[lowbyte];
   1111   1.1  christos       break;
   1112   1.1  christos 
   1113   1.6  christos     case 4:
   1114   1.7  christos       {
   1115   1.7  christos 	/* This is a long instruction: Read the remaning 2 bytes.  */
   1116   1.7  christos 	status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
   1117   1.7  christos 	if (status != 0)
   1118   1.7  christos 	  {
   1119   1.7  christos 	    (*info->memory_error_func) (status, memaddr + 2, info);
   1120   1.7  christos 	    return -1;
   1121   1.7  christos 	  }
   1122   1.7  christos 	insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
   1123   1.7  christos       }
   1124   1.7  christos       break;
   1125   1.7  christos 
   1126   1.7  christos     case 6:
   1127   1.7  christos       {
   1128   1.7  christos 	status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
   1129   1.7  christos 	if (status != 0)
   1130   1.7  christos 	  {
   1131   1.7  christos 	    (*info->memory_error_func) (status, memaddr + 2, info);
   1132   1.7  christos 	    return -1;
   1133   1.7  christos 	  }
   1134   1.7  christos 	insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
   1135   1.7  christos 	insn |= ((unsigned long long) buffer[highbyte] << 40)
   1136   1.7  christos 	  | ((unsigned long long) buffer[lowbyte] << 32);
   1137   1.7  christos       }
   1138   1.7  christos       break;
   1139   1.7  christos 
   1140   1.7  christos     case 8:
   1141   1.7  christos       {
   1142   1.7  christos 	status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
   1143   1.7  christos 	if (status != 0)
   1144   1.7  christos 	  {
   1145   1.7  christos 	    (*info->memory_error_func) (status, memaddr + 2, info);
   1146   1.7  christos 	    return -1;
   1147   1.7  christos 	  }
   1148   1.7  christos 	insn =
   1149   1.7  christos 	  ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
   1150   1.7  christos 	   | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
   1151   1.7  christos       }
   1152   1.1  christos       break;
   1153   1.7  christos 
   1154   1.7  christos     default:
   1155   1.7  christos       /* There is no instruction whose length is not 2, 4, 6, or 8.  */
   1156   1.9  christos       return -1;
   1157   1.1  christos     }
   1158   1.1  christos 
   1159   1.7  christos   pr_debug ("instruction value = %llx\n", insn);
   1160   1.7  christos 
   1161   1.6  christos   /* Set some defaults for the insn info.  */
   1162   1.6  christos   info->insn_info_valid    = 1;
   1163   1.6  christos   info->branch_delay_insns = 0;
   1164   1.7  christos   info->data_size	   = 4;
   1165   1.6  christos   info->insn_type	   = dis_nonbranch;
   1166   1.6  christos   info->target		   = 0;
   1167   1.6  christos   info->target2		   = 0;
   1168   1.6  christos 
   1169   1.6  christos   /* FIXME to be moved in dissasemble_init_for_target.  */
   1170  1.10  christos   info->disassembler_needs_relocs = true;
   1171   1.6  christos 
   1172   1.6  christos   /* Find the first match in the opcode table.  */
   1173   1.6  christos   if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
   1174   1.6  christos     return -1;
   1175   1.6  christos 
   1176   1.6  christos   if (!opcode)
   1177   1.6  christos     {
   1178   1.7  christos       switch (insn_len)
   1179   1.7  christos 	{
   1180   1.7  christos 	case 2:
   1181  1.10  christos 	  (*info->fprintf_styled_func) (info->stream,
   1182  1.10  christos 					dis_style_assembler_directive,
   1183  1.10  christos 					".short");
   1184  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
   1185  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1186  1.10  christos 					"0x%04llx", insn & 0xffff);
   1187   1.7  christos 	  break;
   1188   1.9  christos 
   1189   1.7  christos 	case 4:
   1190  1.10  christos 	  (*info->fprintf_styled_func) (info->stream,
   1191  1.10  christos 					dis_style_assembler_directive,
   1192  1.10  christos 					".word");
   1193  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
   1194  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1195  1.10  christos 					"0x%08llx", insn & 0xffffffff);
   1196   1.7  christos 	  break;
   1197   1.9  christos 
   1198   1.7  christos 	case 6:
   1199  1.10  christos 	  (*info->fprintf_styled_func) (info->stream,
   1200  1.10  christos 					dis_style_assembler_directive,
   1201  1.10  christos 					".long");
   1202  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
   1203  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1204  1.10  christos 				       "0x%08llx", insn & 0xffffffff);
   1205  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
   1206  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1207  1.10  christos 					"0x%04llx", (insn >> 32) & 0xffff);
   1208   1.7  christos 	  break;
   1209   1.9  christos 
   1210   1.7  christos 	case 8:
   1211  1.10  christos 	  (*info->fprintf_styled_func) (info->stream,
   1212  1.10  christos 					dis_style_assembler_directive,
   1213  1.10  christos 					".long");
   1214  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
   1215  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1216  1.10  christos 					"0x%08llx", insn & 0xffffffff);
   1217  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
   1218  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1219  1.10  christos 					"0x%08llx", (insn >> 32));
   1220   1.7  christos 	  break;
   1221   1.9  christos 
   1222   1.7  christos 	default:
   1223   1.9  christos 	  return -1;
   1224   1.7  christos 	}
   1225   1.6  christos 
   1226   1.6  christos       info->insn_type = dis_noninsn;
   1227   1.6  christos       return insn_len;
   1228   1.6  christos     }
   1229   1.6  christos 
   1230   1.6  christos   /* Print the mnemonic.  */
   1231  1.10  christos   (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
   1232  1.10  christos 				"%s", opcode->name);
   1233   1.6  christos 
   1234   1.6  christos   /* Preselect the insn class.  */
   1235   1.7  christos   info->insn_type = arc_opcode_to_insn_type (opcode);
   1236   1.6  christos 
   1237   1.7  christos   pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
   1238   1.1  christos 
   1239   1.7  christos   print_flags (opcode, &insn, info);
   1240   1.6  christos 
   1241   1.6  christos   if (opcode->operands[0] != 0)
   1242  1.10  christos     (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
   1243   1.1  christos 
   1244  1.10  christos   need_comma = false;
   1245  1.10  christos   open_braket = false;
   1246   1.7  christos   arc_infop->operands_count = 0;
   1247   1.1  christos 
   1248   1.6  christos   /* Now extract and print the operands.  */
   1249   1.6  christos   operand = NULL;
   1250   1.8  christos   vpcl = 0;
   1251   1.6  christos   while (operand_iterator_next (&iter, &operand, &value))
   1252   1.6  christos     {
   1253   1.6  christos       if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
   1254   1.1  christos 	{
   1255  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "]");
   1256  1.10  christos 	  open_braket = false;
   1257   1.6  christos 	  continue;
   1258   1.1  christos 	}
   1259   1.1  christos 
   1260   1.6  christos       /* Only take input from real operands.  */
   1261   1.6  christos       if (ARC_OPERAND_IS_FAKE (operand))
   1262   1.6  christos 	continue;
   1263   1.1  christos 
   1264   1.6  christos       if ((operand->flags & ARC_OPERAND_IGNORE)
   1265   1.6  christos 	  && (operand->flags & ARC_OPERAND_IR)
   1266   1.7  christos 	  && value == -1)
   1267   1.6  christos 	continue;
   1268   1.1  christos 
   1269   1.6  christos       if (operand->flags & ARC_OPERAND_COLON)
   1270   1.7  christos 	{
   1271  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, ":");
   1272   1.7  christos 	  continue;
   1273   1.7  christos 	}
   1274   1.1  christos 
   1275   1.6  christos       if (need_comma)
   1276  1.10  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_text,",");
   1277   1.1  christos 
   1278   1.6  christos       if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
   1279   1.1  christos 	{
   1280  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "[");
   1281  1.10  christos 	  open_braket = true;
   1282  1.10  christos 	  need_comma = false;
   1283   1.6  christos 	  continue;
   1284   1.1  christos 	}
   1285   1.6  christos 
   1286  1.10  christos       need_comma = true;
   1287   1.6  christos 
   1288   1.8  christos       if (operand->flags & ARC_OPERAND_PCREL)
   1289   1.8  christos 	{
   1290  1.10  christos 	  rpcl = true;
   1291   1.8  christos 	  vpcl = value;
   1292  1.10  christos 	  rset = true;
   1293   1.8  christos 
   1294   1.8  christos 	  info->target = (bfd_vma) (memaddr & ~3) + value;
   1295   1.8  christos 	}
   1296   1.8  christos       else if (!(operand->flags & ARC_OPERAND_IR))
   1297   1.8  christos 	{
   1298   1.8  christos 	  vpcl = value;
   1299  1.10  christos 	  rset = true;
   1300   1.8  christos 	}
   1301   1.8  christos 
   1302   1.6  christos       /* Print the operand as directed by the flags.  */
   1303   1.6  christos       if (operand->flags & ARC_OPERAND_IR)
   1304   1.1  christos 	{
   1305   1.6  christos 	  const char *rname;
   1306   1.6  christos 
   1307   1.6  christos 	  assert (value >=0 && value < 64);
   1308   1.6  christos 	  rname = arcExtMap_coreRegName (value);
   1309   1.6  christos 	  if (!rname)
   1310   1.6  christos 	    rname = regnames[value];
   1311  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1312  1.10  christos 					"%s", rname);
   1313   1.9  christos 
   1314   1.9  christos 	  /* Check if we have a double register to print.  */
   1315   1.6  christos 	  if (operand->flags & ARC_OPERAND_TRUNCATE)
   1316   1.1  christos 	    {
   1317   1.9  christos 	      if ((value & 0x01) == 0)
   1318   1.9  christos 		{
   1319   1.9  christos 		  rname = arcExtMap_coreRegName (value + 1);
   1320   1.9  christos 		  if (!rname)
   1321   1.9  christos 		    rname = regnames[value + 1];
   1322   1.9  christos 		}
   1323   1.9  christos 	      else
   1324   1.9  christos 		rname = _("\nWarning: illegal use of double register "
   1325   1.9  christos 			  "pair.\n");
   1326  1.10  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1327  1.10  christos 					    "%s", rname);
   1328   1.1  christos 	    }
   1329   1.8  christos 	  if (value == 63)
   1330  1.10  christos 	    rpcl = true;
   1331   1.8  christos 	  else
   1332  1.10  christos 	    rpcl = false;
   1333   1.6  christos 	}
   1334   1.6  christos       else if (operand->flags & ARC_OPERAND_LIMM)
   1335   1.6  christos 	{
   1336   1.6  christos 	  const char *rname = get_auxreg (opcode, value, isa_mask);
   1337   1.6  christos 
   1338   1.6  christos 	  if (rname && open_braket)
   1339  1.10  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1340  1.10  christos 					  "%s", rname);
   1341   1.1  christos 	  else
   1342   1.6  christos 	    {
   1343  1.10  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1344  1.10  christos 					    "%#x", value);
   1345   1.6  christos 	      if (info->insn_type == dis_branch
   1346   1.6  christos 		  || info->insn_type == dis_jsr)
   1347   1.6  christos 		info->target = (bfd_vma) value;
   1348   1.6  christos 	    }
   1349   1.1  christos 	}
   1350   1.6  christos       else if (operand->flags & ARC_OPERAND_SIGNED)
   1351   1.1  christos 	{
   1352   1.6  christos 	  const char *rname = get_auxreg (opcode, value, isa_mask);
   1353   1.6  christos 	  if (rname && open_braket)
   1354  1.10  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1355  1.10  christos 					  "%s", rname);
   1356   1.6  christos 	  else
   1357   1.8  christos 	    {
   1358   1.8  christos 	      if (print_hex)
   1359  1.10  christos 		(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1360  1.10  christos 					      "%#x", value);
   1361   1.8  christos 	      else
   1362  1.10  christos 		(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1363  1.10  christos 					      "%d", value);
   1364   1.8  christos 	    }
   1365   1.1  christos 	}
   1366   1.6  christos       else if (operand->flags & ARC_OPERAND_ADDRTYPE)
   1367   1.7  christos 	{
   1368   1.7  christos 	  const char *addrtype = get_addrtype (value);
   1369  1.10  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_address,
   1370  1.10  christos 					"%s", addrtype);
   1371   1.7  christos 	  /* A colon follow an address type.  */
   1372  1.10  christos 	  need_comma = false;
   1373   1.7  christos 	}
   1374   1.1  christos       else
   1375   1.1  christos 	{
   1376   1.6  christos 	  if (operand->flags & ARC_OPERAND_TRUNCATE
   1377   1.6  christos 	      && !(operand->flags & ARC_OPERAND_ALIGNED32)
   1378   1.6  christos 	      && !(operand->flags & ARC_OPERAND_ALIGNED16)
   1379   1.8  christos 	      && value >= 0 && value <= 14)
   1380   1.8  christos 	    {
   1381   1.8  christos 	      /* Leave/Enter mnemonics.  */
   1382   1.8  christos 	      switch (value)
   1383   1.8  christos 		{
   1384   1.8  christos 		case 0:
   1385  1.10  christos 		  need_comma = false;
   1386   1.8  christos 		  break;
   1387   1.8  christos 		case 1:
   1388  1.10  christos 		  (*info->fprintf_styled_func) (info->stream,
   1389  1.10  christos 						dis_style_register, "r13");
   1390   1.8  christos 		  break;
   1391   1.8  christos 		default:
   1392  1.10  christos 		  (*info->fprintf_styled_func) (info->stream,
   1393  1.10  christos 						dis_style_register, "r13");
   1394  1.10  christos 		  (*info->fprintf_styled_func) (info->stream,
   1395  1.10  christos 						dis_style_text, "-");
   1396  1.10  christos 		  (*info->fprintf_styled_func) (info->stream,
   1397  1.10  christos 						dis_style_register, "%s",
   1398  1.10  christos 						regnames[13 + value - 1]);
   1399   1.8  christos 		  break;
   1400   1.8  christos 		}
   1401  1.10  christos 	      rpcl = false;
   1402  1.10  christos 	      rset = false;
   1403   1.8  christos 	    }
   1404   1.6  christos 	  else
   1405   1.1  christos 	    {
   1406   1.6  christos 	      const char *rname = get_auxreg (opcode, value, isa_mask);
   1407   1.6  christos 	      if (rname && open_braket)
   1408  1.10  christos 		(*info->fprintf_styled_func) (info->stream, dis_style_register,
   1409  1.10  christos 					      "%s", rname);
   1410   1.6  christos 	      else
   1411  1.10  christos 		(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1412  1.10  christos 					      "%#x", value);
   1413   1.1  christos 	    }
   1414   1.1  christos 	}
   1415   1.7  christos 
   1416   1.7  christos       if (operand->flags & ARC_OPERAND_LIMM)
   1417   1.7  christos 	{
   1418   1.7  christos 	  arc_infop->operands[arc_infop->operands_count].kind
   1419   1.7  christos 	    = ARC_OPERAND_KIND_LIMM;
   1420   1.7  christos 	  /* It is not important to have exactly the LIMM indicator
   1421   1.7  christos 	     here.  */
   1422   1.7  christos 	  arc_infop->operands[arc_infop->operands_count].value = 63;
   1423   1.7  christos 	}
   1424   1.7  christos       else
   1425   1.7  christos 	{
   1426   1.7  christos 	  arc_infop->operands[arc_infop->operands_count].value = value;
   1427   1.7  christos 	  arc_infop->operands[arc_infop->operands_count].kind
   1428   1.7  christos 	    = (operand->flags & ARC_OPERAND_IR
   1429   1.7  christos 	       ? ARC_OPERAND_KIND_REG
   1430   1.7  christos 	       : ARC_OPERAND_KIND_SHIMM);
   1431   1.7  christos 	}
   1432   1.7  christos       arc_infop->operands_count ++;
   1433   1.1  christos     }
   1434   1.1  christos 
   1435   1.8  christos   /* Pretty print extra info for pc-relative operands.  */
   1436   1.8  christos   if (rpcl && rset)
   1437   1.8  christos     {
   1438   1.8  christos       if (info->flags & INSN_HAS_RELOC)
   1439   1.8  christos 	/* If the instruction has a reloc associated with it, then the
   1440   1.8  christos 	   offset field in the instruction will actually be the addend
   1441   1.8  christos 	   for the reloc.  (We are using REL type relocs).  In such
   1442   1.8  christos 	   cases, we can ignore the pc when computing addresses, since
   1443   1.8  christos 	   the addend is not currently pc-relative.  */
   1444   1.8  christos 	memaddr = 0;
   1445   1.8  christos 
   1446  1.10  christos       (*info->fprintf_styled_func) (info->stream,
   1447  1.10  christos 				    dis_style_comment_start, "\t;");
   1448   1.8  christos       (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
   1449   1.8  christos     }
   1450   1.8  christos 
   1451   1.6  christos   return insn_len;
   1452   1.1  christos }
   1453   1.1  christos 
   1454   1.1  christos 
   1455   1.6  christos disassembler_ftype
   1456   1.6  christos arc_get_disassembler (bfd *abfd)
   1457   1.6  christos {
   1458   1.7  christos   /* BFD my be absent, if opcodes is invoked from the debugger that
   1459   1.7  christos      has connected to remote target and doesn't have an ELF file.  */
   1460   1.7  christos   if (abfd != NULL)
   1461   1.7  christos     {
   1462   1.7  christos       /* Read the extension insns and registers, if any.  */
   1463   1.7  christos       build_ARC_extmap (abfd);
   1464   1.6  christos #ifdef DEBUG
   1465   1.7  christos       dump_ARC_extmap ();
   1466   1.6  christos #endif
   1467   1.7  christos     }
   1468   1.1  christos 
   1469   1.6  christos   return print_insn_arc;
   1470   1.1  christos }
   1471   1.1  christos 
   1472  1.10  christos /* Indices into option argument vector for options that do require
   1473  1.10  christos    an argument.  Use ARC_OPTION_ARG_NONE for options that don't
   1474  1.10  christos    expect an argument.  */
   1475  1.10  christos typedef enum
   1476  1.10  christos {
   1477  1.10  christos   ARC_OPTION_ARG_NONE = -1,
   1478  1.10  christos   ARC_OPTION_ARG_ARCH,
   1479  1.10  christos   ARC_OPTION_ARG_SIZE
   1480  1.10  christos } arc_option_arg_t;
   1481  1.10  christos 
   1482  1.10  christos /* Valid ARC disassembler options.  */
   1483  1.10  christos static struct
   1484  1.10  christos {
   1485  1.10  christos   const char *name;
   1486  1.10  christos   const char *description;
   1487  1.10  christos   arc_option_arg_t arg;
   1488  1.10  christos } arc_options[] =
   1489  1.10  christos {
   1490  1.10  christos   { "cpu=",       N_("Enforce the designated architecture while decoding."),
   1491  1.10  christos 		  ARC_OPTION_ARG_ARCH },
   1492  1.10  christos   { "dsp",	  N_("Recognize DSP instructions."),
   1493  1.10  christos 		  ARC_OPTION_ARG_NONE },
   1494  1.10  christos   { "spfp",	  N_("Recognize FPX SP instructions."),
   1495  1.10  christos 		  ARC_OPTION_ARG_NONE },
   1496  1.10  christos   { "dpfp",	  N_("Recognize FPX DP instructions."),
   1497  1.10  christos 		  ARC_OPTION_ARG_NONE },
   1498  1.10  christos   { "quarkse_em", N_("Recognize FPU QuarkSE-EM instructions."),
   1499  1.10  christos 		  ARC_OPTION_ARG_NONE },
   1500  1.10  christos   { "fpuda",	  N_("Recognize double assist FPU instructions."),
   1501  1.10  christos 		  ARC_OPTION_ARG_NONE },
   1502  1.10  christos   { "fpus",	  N_("Recognize single precision FPU instructions."),
   1503  1.10  christos 		  ARC_OPTION_ARG_NONE },
   1504  1.10  christos   { "fpud",	  N_("Recognize double precision FPU instructions."),
   1505  1.10  christos 		  ARC_OPTION_ARG_NONE },
   1506  1.10  christos   { "nps400",	  N_("Recognize NPS400 instructions."),
   1507  1.10  christos 		  ARC_OPTION_ARG_NONE },
   1508  1.10  christos   { "hex",	  N_("Use only hexadecimal number to print immediates."),
   1509  1.10  christos 		  ARC_OPTION_ARG_NONE }
   1510  1.10  christos };
   1511  1.10  christos 
   1512  1.10  christos /* Populate the structure for representing ARC's disassembly options.
   1513  1.10  christos    Such a dynamic initialization is desired, because it makes the maintenance
   1514  1.10  christos    easier and also gdb uses this to enable the "disassembler-option".  */
   1515  1.10  christos 
   1516  1.10  christos const disasm_options_and_args_t *
   1517  1.10  christos disassembler_options_arc (void)
   1518  1.10  christos {
   1519  1.10  christos   static disasm_options_and_args_t *opts_and_args;
   1520  1.10  christos 
   1521  1.10  christos   if (opts_and_args == NULL)
   1522  1.10  christos     {
   1523  1.10  christos       disasm_option_arg_t *args;
   1524  1.10  christos       disasm_options_t *opts;
   1525  1.10  christos       size_t i;
   1526  1.10  christos       const size_t nr_of_options = ARRAY_SIZE (arc_options);
   1527  1.10  christos       /* There is a null element at the end of CPU_TYPES, therefore
   1528  1.10  christos 	 NR_OF_CPUS is actually 1 more and that is desired here too.  */
   1529  1.10  christos       const size_t nr_of_cpus = ARRAY_SIZE (cpu_types);
   1530  1.10  christos 
   1531  1.10  christos       opts_and_args = XNEW (disasm_options_and_args_t);
   1532  1.10  christos       opts_and_args->args
   1533  1.10  christos 	= XNEWVEC (disasm_option_arg_t, ARC_OPTION_ARG_SIZE + 1);
   1534  1.10  christos       opts_and_args->options.name
   1535  1.10  christos 	= XNEWVEC (const char *, nr_of_options + 1);
   1536  1.10  christos       opts_and_args->options.description
   1537  1.10  christos 	= XNEWVEC (const char *, nr_of_options + 1);
   1538  1.10  christos       opts_and_args->options.arg
   1539  1.10  christos 	= XNEWVEC (const disasm_option_arg_t *, nr_of_options + 1);
   1540  1.10  christos 
   1541  1.10  christos       /* Populate the arguments for "cpu=" option.  */
   1542  1.10  christos       args = opts_and_args->args;
   1543  1.10  christos       args[ARC_OPTION_ARG_ARCH].name = "ARCH";
   1544  1.10  christos       args[ARC_OPTION_ARG_ARCH].values = XNEWVEC (const char *, nr_of_cpus);
   1545  1.10  christos       for (i = 0; i < nr_of_cpus; ++i)
   1546  1.10  christos 	args[ARC_OPTION_ARG_ARCH].values[i] = cpu_types[i].name;
   1547  1.10  christos       args[ARC_OPTION_ARG_SIZE].name = NULL;
   1548  1.10  christos       args[ARC_OPTION_ARG_SIZE].values = NULL;
   1549  1.10  christos 
   1550  1.10  christos       /* Populate the options.  */
   1551  1.10  christos       opts = &opts_and_args->options;
   1552  1.10  christos       for (i = 0; i < nr_of_options; ++i)
   1553  1.10  christos 	{
   1554  1.10  christos 	  opts->name[i] = arc_options[i].name;
   1555  1.10  christos 	  opts->description[i] = arc_options[i].description;
   1556  1.10  christos 	  if (arc_options[i].arg != ARC_OPTION_ARG_NONE)
   1557  1.10  christos 	    opts->arg[i] = &args[arc_options[i].arg];
   1558  1.10  christos 	  else
   1559  1.10  christos 	    opts->arg[i] = NULL;
   1560  1.10  christos 	}
   1561  1.10  christos       opts->name[nr_of_options] = NULL;
   1562  1.10  christos       opts->description[nr_of_options] = NULL;
   1563  1.10  christos       opts->arg[nr_of_options] = NULL;
   1564  1.10  christos     }
   1565  1.10  christos 
   1566  1.10  christos   return opts_and_args;
   1567  1.10  christos }
   1568  1.10  christos 
   1569  1.10  christos 
   1570   1.6  christos void
   1571   1.6  christos print_arc_disassembler_options (FILE *stream)
   1572   1.1  christos {
   1573  1.10  christos   const disasm_options_and_args_t *opts_and_args;
   1574  1.10  christos   const disasm_option_arg_t *args;
   1575  1.10  christos   const disasm_options_t *opts;
   1576  1.10  christos   size_t i, j;
   1577  1.10  christos   size_t max_len = 0;
   1578  1.10  christos 
   1579  1.10  christos   opts_and_args = disassembler_options_arc ();
   1580  1.10  christos   opts = &opts_and_args->options;
   1581  1.10  christos   args = opts_and_args->args;
   1582  1.10  christos 
   1583  1.10  christos   fprintf (stream, _("\nThe following ARC specific disassembler options are"
   1584  1.10  christos 		     " supported for use \nwith the -M switch (multiple"
   1585  1.10  christos 		     " options should be separated by commas):\n"));
   1586  1.10  christos 
   1587  1.10  christos   /* Find the maximum length for printing options (and their arg name).  */
   1588  1.10  christos   for (i = 0; opts->name[i] != NULL; ++i)
   1589  1.10  christos     {
   1590  1.10  christos       size_t len = strlen (opts->name[i]);
   1591  1.10  christos       len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
   1592  1.10  christos       max_len = (len > max_len) ? len : max_len;
   1593  1.10  christos     }
   1594   1.8  christos 
   1595  1.10  christos   /* Print the options, their arg and description, if any.  */
   1596  1.10  christos   for (i = 0, ++max_len; opts->name[i] != NULL; ++i)
   1597  1.10  christos     {
   1598  1.10  christos       fprintf (stream, "  %s", opts->name[i]);
   1599  1.10  christos       if (opts->arg[i] != NULL)
   1600  1.10  christos 	fprintf (stream, "%s", opts->arg[i]->name);
   1601  1.10  christos       if (opts->description[i] != NULL)
   1602  1.10  christos 	{
   1603  1.10  christos 	  size_t len = strlen (opts->name[i]);
   1604  1.10  christos 	  len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
   1605  1.10  christos 	  fprintf (stream,
   1606  1.10  christos 		   "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
   1607  1.10  christos 	}
   1608  1.10  christos       fprintf (stream, _("\n"));
   1609  1.10  christos     }
   1610   1.6  christos 
   1611  1.10  christos   /* Print the possible values of an argument.  */
   1612  1.10  christos   for (i = 0; args[i].name != NULL; ++i)
   1613   1.8  christos     {
   1614  1.10  christos       size_t len = 3;
   1615  1.10  christos       if (args[i].values == NULL)
   1616  1.10  christos 	continue;
   1617  1.10  christos       fprintf (stream, _("\n\
   1618  1.10  christos   For the options above, the following values are supported for \"%s\":\n   "),
   1619  1.10  christos 	       args[i].name);
   1620  1.10  christos       for (j = 0; args[i].values[j] != NULL; ++j)
   1621  1.10  christos 	{
   1622  1.10  christos 	  fprintf (stream, " %s", args[i].values[j]);
   1623  1.10  christos 	  len += strlen (args[i].values[j]) + 1;
   1624  1.10  christos 	  /* reset line if printed too long.  */
   1625  1.10  christos 	  if (len >= 78)
   1626  1.10  christos 	    {
   1627  1.10  christos 	      fprintf (stream, _("\n   "));
   1628  1.10  christos 	      len = 3;
   1629  1.10  christos 	    }
   1630  1.10  christos 	}
   1631  1.10  christos       fprintf (stream, _("\n"));
   1632  1.10  christos     }
   1633  1.10  christos 
   1634  1.10  christos   fprintf (stream, _("\n"));
   1635   1.1  christos }
   1636   1.1  christos 
   1637   1.7  christos void arc_insn_decode (bfd_vma addr,
   1638   1.7  christos 		      struct disassemble_info *info,
   1639   1.7  christos 		      disassembler_ftype disasm_func,
   1640   1.7  christos 		      struct arc_instruction *insn)
   1641   1.7  christos {
   1642   1.7  christos   const struct arc_opcode *opcode;
   1643   1.7  christos   struct arc_disassemble_info *arc_infop;
   1644   1.7  christos 
   1645   1.7  christos   /* Ensure that insn would be in the reset state.  */
   1646   1.7  christos   memset (insn, 0, sizeof (struct arc_instruction));
   1647   1.7  christos 
   1648   1.7  christos   /* There was an error when disassembling, for example memory read error.  */
   1649   1.7  christos   if (disasm_func (addr, info) < 0)
   1650   1.7  christos     {
   1651  1.10  christos       insn->valid = false;
   1652   1.7  christos       return;
   1653   1.7  christos     }
   1654   1.7  christos 
   1655   1.7  christos   assert (info->private_data != NULL);
   1656   1.7  christos   arc_infop = info->private_data;
   1657   1.7  christos 
   1658   1.7  christos   insn->length  = arc_infop->insn_len;;
   1659   1.7  christos   insn->address = addr;
   1660   1.7  christos 
   1661   1.7  christos   /* Quick exit if memory at this address is not an instruction.  */
   1662   1.7  christos   if (info->insn_type == dis_noninsn)
   1663   1.7  christos     {
   1664  1.10  christos       insn->valid = false;
   1665   1.7  christos       return;
   1666   1.7  christos     }
   1667   1.7  christos 
   1668  1.10  christos   insn->valid = true;
   1669   1.7  christos 
   1670   1.7  christos   opcode = (const struct arc_opcode *) arc_infop->opcode;
   1671   1.7  christos   insn->insn_class = opcode->insn_class;
   1672   1.7  christos   insn->limm_value = arc_infop->limm;
   1673   1.7  christos   insn->limm_p     = arc_infop->limm_p;
   1674   1.7  christos 
   1675   1.7  christos   insn->is_control_flow = (info->insn_type == dis_branch
   1676   1.7  christos 			   || info->insn_type == dis_condbranch
   1677   1.7  christos 			   || info->insn_type == dis_jsr
   1678   1.7  christos 			   || info->insn_type == dis_condjsr);
   1679   1.7  christos 
   1680   1.7  christos   insn->has_delay_slot = info->branch_delay_insns;
   1681   1.7  christos   insn->writeback_mode
   1682   1.7  christos     = (enum arc_ldst_writeback_mode) arc_infop->writeback_mode;
   1683   1.7  christos   insn->data_size_mode = info->data_size;
   1684   1.7  christos   insn->condition_code = arc_infop->condition_code;
   1685   1.7  christos   memcpy (insn->operands, arc_infop->operands,
   1686   1.7  christos 	  sizeof (struct arc_insn_operand) * MAX_INSN_ARGS);
   1687   1.7  christos   insn->operands_count = arc_infop->operands_count;
   1688   1.7  christos }
   1689   1.1  christos 
   1690   1.6  christos /* Local variables:
   1691   1.6  christos    eval: (c-set-style "gnu")
   1692   1.6  christos    indent-tabs-mode: t
   1693   1.6  christos    End:  */
   1694