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