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