1 /* Instruction printing code for the ARC.
2    Copyright (C) 1994-2021 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
init_arc_disasm_info(struct disassemble_info * info)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
add_to_decodelist(insn_class_t insn_class,insn_subclass_t subclass)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
skip_this_opcode(const struct arc_opcode * opcode)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
bfd_getm32(unsigned int data)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
special_flag_p(const char * opname,const char * flgname)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 *
find_format_from_table(struct disassemble_info * info,const struct arc_opcode * arc_table,unsigned long long insn,unsigned int insn_len,unsigned isa_mask,bool * has_limm,bool overlaps)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_func (info->stream,
379 			  _("\nWarning: disassembly may be wrong due to "
380 			    "guessed opcode class choice.\n"
381 			    "Use -M<class[,class]> to select the correct "
382 			    "opcode class(es).\n\t\t\t\t"));
383       return t_op;
384     }
385 
386   return NULL;
387 }
388 
389 /* Find opcode for INSN, trying various different sources.  The instruction
390    length in INSN_LEN will be updated if the instruction requires a LIMM
391    extension.
392 
393    A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
394    initialised, ready to iterate over the operands of the found opcode.  If
395    the found opcode requires a LIMM then the LIMM value will be loaded into a
396    field of ITER.
397 
398    This function returns TRUE in almost all cases, FALSE is reserved to
399    indicate an error (failing to find an opcode is not an error) a returned
400    result of FALSE would indicate that the disassembler can't continue.
401 
402    If no matching opcode is found then the returned result will be TRUE, the
403    value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
404    INSN_LEN will be unchanged.
405 
406    If a matching opcode is found, then the returned result will be TRUE, the
407    opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
408    4 if the instruction requires a LIMM, and the LIMM value will have been
409    loaded into a field of ITER.  Finally, ITER will have been initialised so
410    that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
411    operands.  */
412 
413 static bool
find_format(bfd_vma memaddr,unsigned long long insn,unsigned int * insn_len,unsigned isa_mask,struct disassemble_info * info,const struct arc_opcode ** opcode_result,struct arc_operand_iterator * iter)414 find_format (bfd_vma                       memaddr,
415 	     unsigned long long            insn,
416 	     unsigned int *                insn_len,
417              unsigned                      isa_mask,
418 	     struct disassemble_info *     info,
419              const struct arc_opcode **    opcode_result,
420              struct arc_operand_iterator * iter)
421 {
422   const struct arc_opcode *opcode = NULL;
423   bool needs_limm = false;
424   const extInstruction_t *einsn, *i;
425   unsigned limm = 0;
426   struct arc_disassemble_info *arc_infop = info->private_data;
427 
428   /* First, try the extension instructions.  */
429   if (*insn_len == 4)
430     {
431       einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
432       for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next)
433 	{
434 	  const char *errmsg = NULL;
435 
436 	  opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg);
437 	  if (opcode == NULL)
438 	    {
439 	      (*info->fprintf_func) (info->stream,
440 				     _("An error occurred while generating the "
441 				       "extension instruction operations"));
442 	      *opcode_result = NULL;
443 	      return false;
444 	    }
445 
446 	  opcode = find_format_from_table (info, opcode, insn, *insn_len,
447 					   isa_mask, &needs_limm, false);
448 	}
449     }
450 
451   /* Then, try finding the first match in the opcode table.  */
452   if (opcode == NULL)
453     opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
454 				     isa_mask, &needs_limm, true);
455 
456   if (opcode != NULL && needs_limm)
457     {
458       bfd_byte buffer[4];
459       int status;
460 
461       status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
462                                           4, info);
463       if (status != 0)
464         {
465           opcode = NULL;
466         }
467       else
468         {
469           limm = ARRANGE_ENDIAN (info, buffer);
470           *insn_len += 4;
471         }
472     }
473 
474   if (opcode != NULL)
475     {
476       iter->insn = insn;
477       iter->limm = limm;
478       iter->opcode = opcode;
479       iter->opidx = opcode->operands;
480     }
481 
482   *opcode_result = opcode;
483 
484   /* Update private data.  */
485   arc_infop->opcode = opcode;
486   arc_infop->limm = limm;
487   arc_infop->limm_p = needs_limm;
488 
489   return true;
490 }
491 
492 static void
print_flags(const struct arc_opcode * opcode,unsigned long long * insn,struct disassemble_info * info)493 print_flags (const struct arc_opcode *opcode,
494 	     unsigned long long *insn,
495 	     struct disassemble_info *info)
496 {
497   const unsigned char *flgidx;
498   unsigned int value;
499   struct arc_disassemble_info *arc_infop = info->private_data;
500 
501   /* Now extract and print the flags.  */
502   for (flgidx = opcode->flags; *flgidx; flgidx++)
503     {
504       /* Get a valid flag class.  */
505       const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
506       const unsigned *flgopridx;
507 
508       /* Check first the extensions.  */
509       if (cl_flags->flag_class & F_CLASS_EXTEND)
510 	{
511 	  const char *name;
512 	  value = (insn[0] & 0x1F);
513 
514 	  name = arcExtMap_condCodeName (value);
515 	  if (name)
516 	    {
517 	      (*info->fprintf_func) (info->stream, ".%s", name);
518 	      continue;
519 	    }
520 	}
521 
522       for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
523 	{
524 	  const struct arc_flag_operand *flg_operand =
525 	    &arc_flag_operands[*flgopridx];
526 
527 	  /* Implicit flags are only used for the insn decoder.  */
528 	  if (cl_flags->flag_class & F_CLASS_IMPLICIT)
529 	    {
530 	      if (cl_flags->flag_class & F_CLASS_COND)
531 		arc_infop->condition_code = flg_operand->code;
532 	      else if (cl_flags->flag_class & F_CLASS_WB)
533 		arc_infop->writeback_mode = flg_operand->code;
534 	      else if (cl_flags->flag_class & F_CLASS_ZZ)
535 		info->data_size = flg_operand->code;
536 	      continue;
537 	    }
538 
539 	  if (!flg_operand->favail)
540 	    continue;
541 
542 	  value = (insn[0] >> flg_operand->shift)
543 	    & ((1 << flg_operand->bits) - 1);
544 	  if (value == flg_operand->code)
545 	    {
546 	       /* FIXME!: print correctly nt/t flag.  */
547 	      if (!special_flag_p (opcode->name, flg_operand->name))
548 		(*info->fprintf_func) (info->stream, ".");
549 	      else if (info->insn_type == dis_dref)
550 		{
551 		  switch (flg_operand->name[0])
552 		    {
553 		    case 'b':
554 		      info->data_size = 1;
555 		      break;
556 		    case 'h':
557 		    case 'w':
558 		      info->data_size = 2;
559 		      break;
560 		    default:
561 		      info->data_size = 4;
562 		      break;
563 		    }
564 		}
565 	      if (flg_operand->name[0] == 'd'
566 		  && flg_operand->name[1] == 0)
567 		info->branch_delay_insns = 1;
568 
569 	      /* Check if it is a conditional flag.  */
570 	      if (cl_flags->flag_class & F_CLASS_COND)
571 		{
572 		  if (info->insn_type == dis_jsr)
573 		    info->insn_type = dis_condjsr;
574 		  else if (info->insn_type == dis_branch)
575 		    info->insn_type = dis_condbranch;
576 		  arc_infop->condition_code = flg_operand->code;
577 		}
578 
579 	      /* Check for the write back modes.  */
580 	      if (cl_flags->flag_class & F_CLASS_WB)
581 		arc_infop->writeback_mode = flg_operand->code;
582 
583 	      (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
584 	    }
585 	}
586     }
587 }
588 
589 static const char *
get_auxreg(const struct arc_opcode * opcode,int value,unsigned isa_mask)590 get_auxreg (const struct arc_opcode *opcode,
591 	    int value,
592 	    unsigned isa_mask)
593 {
594   const char *name;
595   unsigned int i;
596   const struct arc_aux_reg *auxr = &arc_aux_regs[0];
597 
598   if (opcode->insn_class != AUXREG)
599     return NULL;
600 
601   name = arcExtMap_auxRegName (value);
602   if (name)
603     return name;
604 
605   for (i = 0; i < arc_num_aux_regs; i++, auxr++)
606     {
607       if (!(auxr->cpu & isa_mask))
608 	continue;
609 
610       if (auxr->subclass != NONE)
611 	return NULL;
612 
613       if (auxr->address == value)
614 	return auxr->name;
615     }
616   return NULL;
617 }
618 
619 /* Convert a value representing an address type to a string used to refer to
620    the address type in assembly code.  */
621 
622 static const char *
get_addrtype(int value)623 get_addrtype (int value)
624 {
625   if (value < 0 || value > addrtypenames_max)
626     return addrtypeunknown;
627 
628   return addrtypenames[value];
629 }
630 
631 /* Calculate the instruction length for an instruction starting with MSB
632    and LSB, the most and least significant byte.  The ISA_MASK is used to
633    filter the instructions considered to only those that are part of the
634    current architecture.
635 
636    The instruction lengths are calculated from the ARC_OPCODE table, and
637    cached for later use.  */
638 
639 static unsigned int
arc_insn_length(bfd_byte msb,bfd_byte lsb,struct disassemble_info * info)640 arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
641 {
642   bfd_byte major_opcode = msb >> 3;
643 
644   switch (info->mach)
645     {
646     case bfd_mach_arc_arc700:
647       /* The nps400 extension set requires this special casing of the
648 	 instruction length calculation.  Right now this is not causing any
649 	 problems as none of the known extensions overlap in opcode space,
650 	 but, if they ever do then we might need to start carrying
651 	 information around in the elf about which extensions are in use.  */
652       if (major_opcode == 0xb)
653         {
654           bfd_byte minor_opcode = lsb & 0x1f;
655 
656 	  if (minor_opcode < 4)
657 	    return 6;
658 	  else if (minor_opcode == 0x10 || minor_opcode == 0x11)
659 	    return 8;
660         }
661       if (major_opcode == 0xa)
662         {
663           return 8;
664         }
665       /* Fall through.  */
666     case bfd_mach_arc_arc600:
667       return (major_opcode > 0xb) ? 2 : 4;
668       break;
669 
670     case bfd_mach_arc_arcv2:
671       return (major_opcode > 0x7) ? 2 : 4;
672       break;
673 
674     default:
675       return 0;
676     }
677 }
678 
679 /* Extract and return the value of OPERAND from the instruction whose value
680    is held in the array INSN.  */
681 
682 static int
extract_operand_value(const struct arc_operand * operand,unsigned long long insn,unsigned limm)683 extract_operand_value (const struct arc_operand *operand,
684 		       unsigned long long insn,
685 		       unsigned limm)
686 {
687   int value;
688 
689   /* Read the limm operand, if required.  */
690   if (operand->flags & ARC_OPERAND_LIMM)
691     /* The second part of the instruction value will have been loaded as
692        part of the find_format call made earlier.  */
693     value = limm;
694   else
695     {
696       if (operand->extract)
697 	value = (*operand->extract) (insn, (bool *) NULL);
698       else
699         {
700           if (operand->flags & ARC_OPERAND_ALIGNED32)
701             {
702               value = (insn >> operand->shift)
703                 & ((1 << (operand->bits - 2)) - 1);
704               value = value << 2;
705             }
706           else
707             {
708               value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
709             }
710           if (operand->flags & ARC_OPERAND_SIGNED)
711             {
712               int signbit = 1 << (operand->bits - 1);
713               value = (value ^ signbit) - signbit;
714             }
715         }
716     }
717 
718   return value;
719 }
720 
721 /* Find the next operand, and the operands value from ITER.  Return TRUE if
722    there is another operand, otherwise return FALSE.  If there is an
723    operand returned then the operand is placed into OPERAND, and the value
724    into VALUE.  If there is no operand returned then OPERAND and VALUE are
725    unchanged.  */
726 
727 static bool
operand_iterator_next(struct arc_operand_iterator * iter,const struct arc_operand ** operand,int * value)728 operand_iterator_next (struct arc_operand_iterator *iter,
729                        const struct arc_operand **operand,
730                        int *value)
731 {
732   if (*iter->opidx == 0)
733     {
734       *operand = NULL;
735       return false;
736     }
737 
738   *operand = &arc_operands[*iter->opidx];
739   *value = extract_operand_value (*operand, iter->insn, iter->limm);
740   iter->opidx++;
741 
742   return true;
743 }
744 
745 /* Helper for parsing the options.  */
746 
747 static void
parse_option(const char * option)748 parse_option (const char *option)
749 {
750   if (disassembler_options_cmp (option, "dsp") == 0)
751     add_to_decodelist (DSP, NONE);
752 
753   else if (disassembler_options_cmp (option, "spfp") == 0)
754     add_to_decodelist (FLOAT, SPX);
755 
756   else if (disassembler_options_cmp (option, "dpfp") == 0)
757     add_to_decodelist (FLOAT, DPX);
758 
759   else if (disassembler_options_cmp (option, "quarkse_em") == 0)
760     {
761       add_to_decodelist (FLOAT, DPX);
762       add_to_decodelist (FLOAT, SPX);
763       add_to_decodelist (FLOAT, QUARKSE1);
764       add_to_decodelist (FLOAT, QUARKSE2);
765     }
766 
767   else if (disassembler_options_cmp (option, "fpuda") == 0)
768     add_to_decodelist (FLOAT, DPA);
769 
770   else if (disassembler_options_cmp (option, "nps400") == 0)
771     {
772       add_to_decodelist (ACL, NPS400);
773       add_to_decodelist (ARITH, NPS400);
774       add_to_decodelist (BITOP, NPS400);
775       add_to_decodelist (BMU, NPS400);
776       add_to_decodelist (CONTROL, NPS400);
777       add_to_decodelist (DMA, NPS400);
778       add_to_decodelist (DPI, NPS400);
779       add_to_decodelist (MEMORY, NPS400);
780       add_to_decodelist (MISC, NPS400);
781       add_to_decodelist (NET, NPS400);
782       add_to_decodelist (PMU, NPS400);
783       add_to_decodelist (PROTOCOL_DECODE, NPS400);
784       add_to_decodelist (ULTRAIP, NPS400);
785     }
786 
787   else if (disassembler_options_cmp (option, "fpus") == 0)
788     {
789       add_to_decodelist (FLOAT, SP);
790       add_to_decodelist (FLOAT, CVT);
791     }
792 
793   else if (disassembler_options_cmp (option, "fpud") == 0)
794     {
795       add_to_decodelist (FLOAT, DP);
796       add_to_decodelist (FLOAT, CVT);
797     }
798   else if (startswith (option, "hex"))
799     print_hex = true;
800   else
801     /* xgettext:c-format */
802     opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
803 }
804 
805 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA)			\
806   { #NAME, ARC_OPCODE_ARC600, "ARC600" }
807 #define ARC_CPU_TYPE_A7xx(NAME,EXTRA)			\
808   { #NAME, ARC_OPCODE_ARC700, "ARC700" }
809 #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA)			\
810   { #NAME,  ARC_OPCODE_ARCv2EM, "ARC EM" }
811 #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA)			\
812   { #NAME,  ARC_OPCODE_ARCv2HS, "ARC HS" }
813 #define ARC_CPU_TYPE_NONE				\
814   { 0, 0, 0 }
815 
816 /* A table of CPU names and opcode sets.  */
817 static const struct cpu_type
818 {
819   const char *name;
820   unsigned flags;
821   const char *isa;
822 }
823   cpu_types[] =
824 {
825   #include "elf/arc-cpu.def"
826 };
827 
828 /* Helper for parsing the CPU options.  Accept any of the ARC architectures
829    values.  OPTION should be a value passed to cpu=.  */
830 
831 static unsigned
parse_cpu_option(const char * option)832 parse_cpu_option (const char *option)
833 {
834   int i;
835 
836   for (i = 0; cpu_types[i].name; ++i)
837     {
838       if (!disassembler_options_cmp (cpu_types[i].name, option))
839 	{
840 	  return cpu_types[i].flags;
841 	}
842     }
843 
844   /* xgettext:c-format */
845   opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
846   return ARC_OPCODE_NONE;
847 }
848 
849 /* Go over the options list and parse it.  */
850 
851 static void
parse_disassembler_options(const char * options)852 parse_disassembler_options (const char *options)
853 {
854   const char *option;
855 
856   if (options == NULL)
857     return;
858 
859   /* Disassembler might be reused for difference CPU's, and cpu option set for
860      the first one shouldn't be applied to second (which might not have
861      explicit cpu in its options.  Therefore it is required to reset enforced
862      CPU when new options are being parsed.  */
863   enforced_isa_mask = ARC_OPCODE_NONE;
864 
865   FOR_EACH_DISASSEMBLER_OPTION (option, options)
866     {
867       /* A CPU option?  Cannot use STRING_COMMA_LEN because strncmp is also a
868 	 preprocessor macro.  */
869       if (strncmp (option, "cpu=", 4) == 0)
870 	/* Strip leading `cpu=`.  */
871 	enforced_isa_mask = parse_cpu_option (option + 4);
872       else
873 	parse_option (option);
874     }
875 }
876 
877 /* Return the instruction type for an instruction described by OPCODE.  */
878 
879 static enum dis_insn_type
arc_opcode_to_insn_type(const struct arc_opcode * opcode)880 arc_opcode_to_insn_type (const struct arc_opcode *opcode)
881 {
882   enum dis_insn_type insn_type;
883 
884   switch (opcode->insn_class)
885     {
886     case BRANCH:
887     case BBIT0:
888     case BBIT1:
889     case BI:
890     case BIH:
891     case BRCC:
892     case EI:
893     case JLI:
894     case JUMP:
895     case LOOP:
896       if (!strncmp (opcode->name, "bl", 2)
897 	  || !strncmp (opcode->name, "jl", 2))
898 	{
899 	  if (opcode->subclass == COND)
900 	    insn_type = dis_condjsr;
901 	  else
902 	    insn_type = dis_jsr;
903 	}
904       else
905 	{
906 	  if (opcode->subclass == COND)
907 	    insn_type = dis_condbranch;
908 	  else
909 	    insn_type = dis_branch;
910 	}
911       break;
912     case LOAD:
913     case STORE:
914     case MEMORY:
915     case ENTER:
916     case PUSH:
917     case POP:
918       insn_type = dis_dref;
919       break;
920     case LEAVE:
921       insn_type = dis_branch;
922       break;
923     default:
924       insn_type = dis_nonbranch;
925       break;
926     }
927 
928   return insn_type;
929 }
930 
931 /* Disassemble ARC instructions.  */
932 
933 static int
print_insn_arc(bfd_vma memaddr,struct disassemble_info * info)934 print_insn_arc (bfd_vma memaddr,
935 		struct disassemble_info *info)
936 {
937   bfd_byte buffer[8];
938   unsigned int highbyte, lowbyte;
939   int status;
940   unsigned int insn_len;
941   unsigned long long insn = 0;
942   unsigned isa_mask = ARC_OPCODE_NONE;
943   const struct arc_opcode *opcode;
944   bool need_comma;
945   bool open_braket;
946   int size;
947   const struct arc_operand *operand;
948   int value, vpcl;
949   struct arc_operand_iterator iter;
950   struct arc_disassemble_info *arc_infop;
951   bool rpcl = false, rset = false;
952 
953   if (info->disassembler_options)
954     {
955       parse_disassembler_options (info->disassembler_options);
956 
957       /* Avoid repeated parsing of the options.  */
958       info->disassembler_options = NULL;
959     }
960 
961   if (info->private_data == NULL && !init_arc_disasm_info (info))
962     return -1;
963 
964   memset (&iter, 0, sizeof (iter));
965   highbyte  = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
966   lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
967 
968   /* Figure out CPU type, unless it was enforced via disassembler options.  */
969   if (enforced_isa_mask == ARC_OPCODE_NONE)
970     {
971       Elf_Internal_Ehdr *header = NULL;
972 
973       if (info->section && info->section->owner)
974 	header = elf_elfheader (info->section->owner);
975 
976       switch (info->mach)
977 	{
978 	case bfd_mach_arc_arc700:
979 	  isa_mask = ARC_OPCODE_ARC700;
980 	  break;
981 
982 	case bfd_mach_arc_arc600:
983 	  isa_mask = ARC_OPCODE_ARC600;
984 	  break;
985 
986 	case bfd_mach_arc_arcv2:
987 	default:
988 	  isa_mask = ARC_OPCODE_ARCv2EM;
989 	  /* TODO: Perhaps remove definition of header since it is only used at
990 	     this location.  */
991 	  if (header != NULL
992 	      && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
993 	    isa_mask = ARC_OPCODE_ARCv2HS;
994 	  break;
995 	}
996     }
997   else
998     isa_mask = enforced_isa_mask;
999 
1000   if (isa_mask == ARC_OPCODE_ARCv2HS)
1001     {
1002       /* FPU instructions are not extensions for HS.  */
1003       add_to_decodelist (FLOAT, SP);
1004       add_to_decodelist (FLOAT, DP);
1005       add_to_decodelist (FLOAT, CVT);
1006     }
1007 
1008   /* This variable may be set by the instruction decoder.  It suggests
1009      the number of bytes objdump should display on a single line.  If
1010      the instruction decoder sets this, it should always set it to
1011      the same value in order to get reasonable looking output.  */
1012   info->bytes_per_line  = 8;
1013 
1014   /* In the next lines, we set two info variables control the way
1015      objdump displays the raw data.  For example, if bytes_per_line is
1016      8 and bytes_per_chunk is 4, the output will look like this:
1017      00:   00000000 00000000
1018      with the chunks displayed according to "display_endian".  */
1019   if (info->section
1020       && !(info->section->flags & SEC_CODE))
1021     {
1022       /* This is not a CODE section.  */
1023       switch (info->section->size)
1024 	{
1025 	case 1:
1026 	case 2:
1027 	case 4:
1028 	  size = info->section->size;
1029 	  break;
1030 	default:
1031 	  size = (info->section->size & 0x01) ? 1 : 4;
1032 	  break;
1033 	}
1034       info->bytes_per_chunk = 1;
1035       info->display_endian = info->endian;
1036     }
1037   else
1038     {
1039       size = 2;
1040       info->bytes_per_chunk = 2;
1041       info->display_endian = info->endian;
1042     }
1043 
1044   /* Read the insn into a host word.  */
1045   status = (*info->read_memory_func) (memaddr, buffer, size, info);
1046 
1047   if (status != 0)
1048     {
1049       (*info->memory_error_func) (status, memaddr, info);
1050       return -1;
1051     }
1052 
1053   if (info->section
1054       && !(info->section->flags & SEC_CODE))
1055     {
1056       /* Data section.  */
1057       unsigned long data;
1058 
1059       data = bfd_get_bits (buffer, size * 8,
1060 			   info->display_endian == BFD_ENDIAN_BIG);
1061       switch (size)
1062 	{
1063 	case 1:
1064 	  (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
1065 	  break;
1066 	case 2:
1067 	  (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
1068 	  break;
1069 	case 4:
1070 	  (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
1071 	  break;
1072 	default:
1073 	  return -1;
1074 	}
1075       return size;
1076     }
1077 
1078   insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
1079   pr_debug ("instruction length = %d bytes\n", insn_len);
1080   if (insn_len == 0)
1081     return -1;
1082 
1083   arc_infop = info->private_data;
1084   arc_infop->insn_len = insn_len;
1085 
1086   switch (insn_len)
1087     {
1088     case 2:
1089       insn = (buffer[highbyte] << 8) | buffer[lowbyte];
1090       break;
1091 
1092     case 4:
1093       {
1094 	/* This is a long instruction: Read the remaning 2 bytes.  */
1095 	status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
1096 	if (status != 0)
1097 	  {
1098 	    (*info->memory_error_func) (status, memaddr + 2, info);
1099 	    return -1;
1100 	  }
1101 	insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
1102       }
1103       break;
1104 
1105     case 6:
1106       {
1107 	status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
1108 	if (status != 0)
1109 	  {
1110 	    (*info->memory_error_func) (status, memaddr + 2, info);
1111 	    return -1;
1112 	  }
1113 	insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
1114 	insn |= ((unsigned long long) buffer[highbyte] << 40)
1115 	  | ((unsigned long long) buffer[lowbyte] << 32);
1116       }
1117       break;
1118 
1119     case 8:
1120       {
1121 	status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
1122 	if (status != 0)
1123 	  {
1124 	    (*info->memory_error_func) (status, memaddr + 2, info);
1125 	    return -1;
1126 	  }
1127 	insn =
1128 	  ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
1129 	   | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
1130       }
1131       break;
1132 
1133     default:
1134       /* There is no instruction whose length is not 2, 4, 6, or 8.  */
1135       return -1;
1136     }
1137 
1138   pr_debug ("instruction value = %llx\n", insn);
1139 
1140   /* Set some defaults for the insn info.  */
1141   info->insn_info_valid    = 1;
1142   info->branch_delay_insns = 0;
1143   info->data_size	   = 4;
1144   info->insn_type	   = dis_nonbranch;
1145   info->target		   = 0;
1146   info->target2		   = 0;
1147 
1148   /* FIXME to be moved in dissasemble_init_for_target.  */
1149   info->disassembler_needs_relocs = true;
1150 
1151   /* Find the first match in the opcode table.  */
1152   if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
1153     return -1;
1154 
1155   if (!opcode)
1156     {
1157       switch (insn_len)
1158 	{
1159 	case 2:
1160 	  (*info->fprintf_func) (info->stream, ".shor\t%#04llx",
1161 				 insn & 0xffff);
1162 	  break;
1163 
1164 	case 4:
1165 	  (*info->fprintf_func) (info->stream, ".word\t%#08llx",
1166 				 insn & 0xffffffff);
1167 	  break;
1168 
1169 	case 6:
1170 	  (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1171 				 insn & 0xffffffff);
1172 	  (*info->fprintf_func) (info->stream, ".long\t%#04llx",
1173 				 (insn >> 32) & 0xffff);
1174 	  break;
1175 
1176 	case 8:
1177 	  (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1178 				 insn & 0xffffffff);
1179 	  (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1180 				 insn >> 32);
1181 	  break;
1182 
1183 	default:
1184 	  return -1;
1185 	}
1186 
1187       info->insn_type = dis_noninsn;
1188       return insn_len;
1189     }
1190 
1191   /* Print the mnemonic.  */
1192   (*info->fprintf_func) (info->stream, "%s", opcode->name);
1193 
1194   /* Preselect the insn class.  */
1195   info->insn_type = arc_opcode_to_insn_type (opcode);
1196 
1197   pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
1198 
1199   print_flags (opcode, &insn, info);
1200 
1201   if (opcode->operands[0] != 0)
1202     (*info->fprintf_func) (info->stream, "\t");
1203 
1204   need_comma = false;
1205   open_braket = false;
1206   arc_infop->operands_count = 0;
1207 
1208   /* Now extract and print the operands.  */
1209   operand = NULL;
1210   vpcl = 0;
1211   while (operand_iterator_next (&iter, &operand, &value))
1212     {
1213       if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1214 	{
1215 	  (*info->fprintf_func) (info->stream, "]");
1216 	  open_braket = false;
1217 	  continue;
1218 	}
1219 
1220       /* Only take input from real operands.  */
1221       if (ARC_OPERAND_IS_FAKE (operand))
1222 	continue;
1223 
1224       if ((operand->flags & ARC_OPERAND_IGNORE)
1225 	  && (operand->flags & ARC_OPERAND_IR)
1226 	  && value == -1)
1227 	continue;
1228 
1229       if (operand->flags & ARC_OPERAND_COLON)
1230 	{
1231 	  (*info->fprintf_func) (info->stream, ":");
1232 	  continue;
1233 	}
1234 
1235       if (need_comma)
1236 	(*info->fprintf_func) (info->stream, ",");
1237 
1238       if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1239 	{
1240 	  (*info->fprintf_func) (info->stream, "[");
1241 	  open_braket = true;
1242 	  need_comma = false;
1243 	  continue;
1244 	}
1245 
1246       need_comma = true;
1247 
1248       if (operand->flags & ARC_OPERAND_PCREL)
1249 	{
1250 	  rpcl = true;
1251 	  vpcl = value;
1252 	  rset = true;
1253 
1254 	  info->target = (bfd_vma) (memaddr & ~3) + value;
1255 	}
1256       else if (!(operand->flags & ARC_OPERAND_IR))
1257 	{
1258 	  vpcl = value;
1259 	  rset = true;
1260 	}
1261 
1262       /* Print the operand as directed by the flags.  */
1263       if (operand->flags & ARC_OPERAND_IR)
1264 	{
1265 	  const char *rname;
1266 
1267 	  assert (value >=0 && value < 64);
1268 	  rname = arcExtMap_coreRegName (value);
1269 	  if (!rname)
1270 	    rname = regnames[value];
1271 	  (*info->fprintf_func) (info->stream, "%s", rname);
1272 
1273 	  /* Check if we have a double register to print.  */
1274 	  if (operand->flags & ARC_OPERAND_TRUNCATE)
1275 	    {
1276 	      if ((value & 0x01) == 0)
1277 		{
1278 		  rname = arcExtMap_coreRegName (value + 1);
1279 		  if (!rname)
1280 		    rname = regnames[value + 1];
1281 		}
1282 	      else
1283 		rname = _("\nWarning: illegal use of double register "
1284 			  "pair.\n");
1285 	      (*info->fprintf_func) (info->stream, "%s", rname);
1286 	    }
1287 	  if (value == 63)
1288 	    rpcl = true;
1289 	  else
1290 	    rpcl = false;
1291 	}
1292       else if (operand->flags & ARC_OPERAND_LIMM)
1293 	{
1294 	  const char *rname = get_auxreg (opcode, value, isa_mask);
1295 
1296 	  if (rname && open_braket)
1297 	    (*info->fprintf_func) (info->stream, "%s", rname);
1298 	  else
1299 	    {
1300 	      (*info->fprintf_func) (info->stream, "%#x", value);
1301 	      if (info->insn_type == dis_branch
1302 		  || info->insn_type == dis_jsr)
1303 		info->target = (bfd_vma) value;
1304 	    }
1305 	}
1306       else if (operand->flags & ARC_OPERAND_SIGNED)
1307 	{
1308 	  const char *rname = get_auxreg (opcode, value, isa_mask);
1309 	  if (rname && open_braket)
1310 	    (*info->fprintf_func) (info->stream, "%s", rname);
1311 	  else
1312 	    {
1313 	      if (print_hex)
1314 		(*info->fprintf_func) (info->stream, "%#x", value);
1315 	      else
1316 		(*info->fprintf_func) (info->stream, "%d", value);
1317 	    }
1318 	}
1319       else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1320 	{
1321 	  const char *addrtype = get_addrtype (value);
1322 	  (*info->fprintf_func) (info->stream, "%s", addrtype);
1323 	  /* A colon follow an address type.  */
1324 	  need_comma = false;
1325 	}
1326       else
1327 	{
1328 	  if (operand->flags & ARC_OPERAND_TRUNCATE
1329 	      && !(operand->flags & ARC_OPERAND_ALIGNED32)
1330 	      && !(operand->flags & ARC_OPERAND_ALIGNED16)
1331 	      && value >= 0 && value <= 14)
1332 	    {
1333 	      /* Leave/Enter mnemonics.  */
1334 	      switch (value)
1335 		{
1336 		case 0:
1337 		  need_comma = false;
1338 		  break;
1339 		case 1:
1340 		  (*info->fprintf_func) (info->stream, "r13");
1341 		  break;
1342 		default:
1343 		  (*info->fprintf_func) (info->stream, "r13-%s",
1344 					 regnames[13 + value - 1]);
1345 		  break;
1346 		}
1347 	      rpcl = false;
1348 	      rset = false;
1349 	    }
1350 	  else
1351 	    {
1352 	      const char *rname = get_auxreg (opcode, value, isa_mask);
1353 	      if (rname && open_braket)
1354 		(*info->fprintf_func) (info->stream, "%s", rname);
1355 	      else
1356 		(*info->fprintf_func) (info->stream, "%#x", value);
1357 	    }
1358 	}
1359 
1360       if (operand->flags & ARC_OPERAND_LIMM)
1361 	{
1362 	  arc_infop->operands[arc_infop->operands_count].kind
1363 	    = ARC_OPERAND_KIND_LIMM;
1364 	  /* It is not important to have exactly the LIMM indicator
1365 	     here.  */
1366 	  arc_infop->operands[arc_infop->operands_count].value = 63;
1367 	}
1368       else
1369 	{
1370 	  arc_infop->operands[arc_infop->operands_count].value = value;
1371 	  arc_infop->operands[arc_infop->operands_count].kind
1372 	    = (operand->flags & ARC_OPERAND_IR
1373 	       ? ARC_OPERAND_KIND_REG
1374 	       : ARC_OPERAND_KIND_SHIMM);
1375 	}
1376       arc_infop->operands_count ++;
1377     }
1378 
1379   /* Pretty print extra info for pc-relative operands.  */
1380   if (rpcl && rset)
1381     {
1382       if (info->flags & INSN_HAS_RELOC)
1383 	/* If the instruction has a reloc associated with it, then the
1384 	   offset field in the instruction will actually be the addend
1385 	   for the reloc.  (We are using REL type relocs).  In such
1386 	   cases, we can ignore the pc when computing addresses, since
1387 	   the addend is not currently pc-relative.  */
1388 	memaddr = 0;
1389 
1390       (*info->fprintf_func) (info->stream, "\t;");
1391       (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
1392     }
1393 
1394   return insn_len;
1395 }
1396 
1397 
1398 disassembler_ftype
arc_get_disassembler(bfd * abfd)1399 arc_get_disassembler (bfd *abfd)
1400 {
1401   /* BFD my be absent, if opcodes is invoked from the debugger that
1402      has connected to remote target and doesn't have an ELF file.  */
1403   if (abfd != NULL)
1404     {
1405       /* Read the extension insns and registers, if any.  */
1406       build_ARC_extmap (abfd);
1407 #ifdef DEBUG
1408       dump_ARC_extmap ();
1409 #endif
1410     }
1411 
1412   return print_insn_arc;
1413 }
1414 
1415 /* Indices into option argument vector for options that do require
1416    an argument.  Use ARC_OPTION_ARG_NONE for options that don't
1417    expect an argument.  */
1418 typedef enum
1419 {
1420   ARC_OPTION_ARG_NONE = -1,
1421   ARC_OPTION_ARG_ARCH,
1422   ARC_OPTION_ARG_SIZE
1423 } arc_option_arg_t;
1424 
1425 /* Valid ARC disassembler options.  */
1426 static struct
1427 {
1428   const char *name;
1429   const char *description;
1430   arc_option_arg_t arg;
1431 } arc_options[] =
1432 {
1433   { "cpu=",       N_("Enforce the designated architecture while decoding."),
1434 		  ARC_OPTION_ARG_ARCH },
1435   { "dsp",	  N_("Recognize DSP instructions."),
1436 		  ARC_OPTION_ARG_NONE },
1437   { "spfp",	  N_("Recognize FPX SP instructions."),
1438 		  ARC_OPTION_ARG_NONE },
1439   { "dpfp",	  N_("Recognize FPX DP instructions."),
1440 		  ARC_OPTION_ARG_NONE },
1441   { "quarkse_em", N_("Recognize FPU QuarkSE-EM instructions."),
1442 		  ARC_OPTION_ARG_NONE },
1443   { "fpuda",	  N_("Recognize double assist FPU instructions."),
1444 		  ARC_OPTION_ARG_NONE },
1445   { "fpus",	  N_("Recognize single precision FPU instructions."),
1446 		  ARC_OPTION_ARG_NONE },
1447   { "fpud",	  N_("Recognize double precision FPU instructions."),
1448 		  ARC_OPTION_ARG_NONE },
1449   { "nps400",	  N_("Recognize NPS400 instructions."),
1450 		  ARC_OPTION_ARG_NONE },
1451   { "hex",	  N_("Use only hexadecimal number to print immediates."),
1452 		  ARC_OPTION_ARG_NONE }
1453 };
1454 
1455 /* Populate the structure for representing ARC's disassembly options.
1456    Such a dynamic initialization is desired, because it makes the maintenance
1457    easier and also gdb uses this to enable the "disassembler-option".  */
1458 
1459 const disasm_options_and_args_t *
disassembler_options_arc(void)1460 disassembler_options_arc (void)
1461 {
1462   static disasm_options_and_args_t *opts_and_args;
1463 
1464   if (opts_and_args == NULL)
1465     {
1466       disasm_option_arg_t *args;
1467       disasm_options_t *opts;
1468       size_t i;
1469       const size_t nr_of_options = ARRAY_SIZE (arc_options);
1470       /* There is a null element at the end of CPU_TYPES, therefore
1471 	 NR_OF_CPUS is actually 1 more and that is desired here too.  */
1472       const size_t nr_of_cpus = ARRAY_SIZE (cpu_types);
1473 
1474       opts_and_args = XNEW (disasm_options_and_args_t);
1475       opts_and_args->args
1476 	= XNEWVEC (disasm_option_arg_t, ARC_OPTION_ARG_SIZE + 1);
1477       opts_and_args->options.name
1478 	= XNEWVEC (const char *, nr_of_options + 1);
1479       opts_and_args->options.description
1480 	= XNEWVEC (const char *, nr_of_options + 1);
1481       opts_and_args->options.arg
1482 	= XNEWVEC (const disasm_option_arg_t *, nr_of_options + 1);
1483 
1484       /* Populate the arguments for "cpu=" option.  */
1485       args = opts_and_args->args;
1486       args[ARC_OPTION_ARG_ARCH].name = "ARCH";
1487       args[ARC_OPTION_ARG_ARCH].values = XNEWVEC (const char *, nr_of_cpus);
1488       for (i = 0; i < nr_of_cpus; ++i)
1489 	args[ARC_OPTION_ARG_ARCH].values[i] = cpu_types[i].name;
1490       args[ARC_OPTION_ARG_SIZE].name = NULL;
1491       args[ARC_OPTION_ARG_SIZE].values = NULL;
1492 
1493       /* Populate the options.  */
1494       opts = &opts_and_args->options;
1495       for (i = 0; i < nr_of_options; ++i)
1496 	{
1497 	  opts->name[i] = arc_options[i].name;
1498 	  opts->description[i] = arc_options[i].description;
1499 	  if (arc_options[i].arg != ARC_OPTION_ARG_NONE)
1500 	    opts->arg[i] = &args[arc_options[i].arg];
1501 	  else
1502 	    opts->arg[i] = NULL;
1503 	}
1504       opts->name[nr_of_options] = NULL;
1505       opts->description[nr_of_options] = NULL;
1506       opts->arg[nr_of_options] = NULL;
1507     }
1508 
1509   return opts_and_args;
1510 }
1511 
1512 
1513 void
print_arc_disassembler_options(FILE * stream)1514 print_arc_disassembler_options (FILE *stream)
1515 {
1516   const disasm_options_and_args_t *opts_and_args;
1517   const disasm_option_arg_t *args;
1518   const disasm_options_t *opts;
1519   size_t i, j;
1520   size_t max_len = 0;
1521 
1522   opts_and_args = disassembler_options_arc ();
1523   opts = &opts_and_args->options;
1524   args = opts_and_args->args;
1525 
1526   fprintf (stream, _("\nThe following ARC specific disassembler options are"
1527 		     " supported for use \nwith the -M switch (multiple"
1528 		     " options should be separated by commas):\n"));
1529 
1530   /* Find the maximum length for printing options (and their arg name).  */
1531   for (i = 0; opts->name[i] != NULL; ++i)
1532     {
1533       size_t len = strlen (opts->name[i]);
1534       len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
1535       max_len = (len > max_len) ? len : max_len;
1536     }
1537 
1538   /* Print the options, their arg and description, if any.  */
1539   for (i = 0, ++max_len; opts->name[i] != NULL; ++i)
1540     {
1541       fprintf (stream, "  %s", opts->name[i]);
1542       if (opts->arg[i] != NULL)
1543 	fprintf (stream, "%s", opts->arg[i]->name);
1544       if (opts->description[i] != NULL)
1545 	{
1546 	  size_t len = strlen (opts->name[i]);
1547 	  len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
1548 	  fprintf (stream,
1549 		   "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
1550 	}
1551       fprintf (stream, _("\n"));
1552     }
1553 
1554   /* Print the possible values of an argument.  */
1555   for (i = 0; args[i].name != NULL; ++i)
1556     {
1557       size_t len = 3;
1558       fprintf (stream, _("\n\
1559   For the options above, the following values are supported for \"%s\":\n   "),
1560 	       args[i].name);
1561       for (j = 0; args[i].values[j] != NULL; ++j)
1562 	{
1563 	  fprintf (stream, " %s", args[i].values[j]);
1564 	  len += strlen (args[i].values[j]) + 1;
1565 	  /* reset line if printed too long.  */
1566 	  if (len >= 78)
1567 	    {
1568 	      fprintf (stream, _("\n   "));
1569 	      len = 3;
1570 	    }
1571 	}
1572       fprintf (stream, _("\n"));
1573     }
1574 
1575   fprintf (stream, _("\n"));
1576 }
1577 
arc_insn_decode(bfd_vma addr,struct disassemble_info * info,disassembler_ftype disasm_func,struct arc_instruction * insn)1578 void arc_insn_decode (bfd_vma addr,
1579 		      struct disassemble_info *info,
1580 		      disassembler_ftype disasm_func,
1581 		      struct arc_instruction *insn)
1582 {
1583   const struct arc_opcode *opcode;
1584   struct arc_disassemble_info *arc_infop;
1585 
1586   /* Ensure that insn would be in the reset state.  */
1587   memset (insn, 0, sizeof (struct arc_instruction));
1588 
1589   /* There was an error when disassembling, for example memory read error.  */
1590   if (disasm_func (addr, info) < 0)
1591     {
1592       insn->valid = false;
1593       return;
1594     }
1595 
1596   assert (info->private_data != NULL);
1597   arc_infop = info->private_data;
1598 
1599   insn->length  = arc_infop->insn_len;;
1600   insn->address = addr;
1601 
1602   /* Quick exit if memory at this address is not an instruction.  */
1603   if (info->insn_type == dis_noninsn)
1604     {
1605       insn->valid = false;
1606       return;
1607     }
1608 
1609   insn->valid = true;
1610 
1611   opcode = (const struct arc_opcode *) arc_infop->opcode;
1612   insn->insn_class = opcode->insn_class;
1613   insn->limm_value = arc_infop->limm;
1614   insn->limm_p     = arc_infop->limm_p;
1615 
1616   insn->is_control_flow = (info->insn_type == dis_branch
1617 			   || info->insn_type == dis_condbranch
1618 			   || info->insn_type == dis_jsr
1619 			   || info->insn_type == dis_condjsr);
1620 
1621   insn->has_delay_slot = info->branch_delay_insns;
1622   insn->writeback_mode
1623     = (enum arc_ldst_writeback_mode) arc_infop->writeback_mode;
1624   insn->data_size_mode = info->data_size;
1625   insn->condition_code = arc_infop->condition_code;
1626   memcpy (insn->operands, arc_infop->operands,
1627 	  sizeof (struct arc_insn_operand) * MAX_INSN_ARGS);
1628   insn->operands_count = arc_infop->operands_count;
1629 }
1630 
1631 /* Local variables:
1632    eval: (c-set-style "gnu")
1633    indent-tabs-mode: t
1634    End:  */
1635