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