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