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