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