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