Update year range in copyright notice of all files.
[external/binutils.git] / opcodes / arc-dis.c
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
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 /* Add a new element to the decode list.  */
112
113 static void
114 add_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
128 static bfd_boolean
129 skip_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
159 static bfd_vma
160 bfd_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
169 static bfd_boolean
170 special_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
200 static const struct arc_opcode *
201 find_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
357 static bfd_boolean
358 find_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, "\
383 An 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
428 static void
429 print_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
507 static const char *
508 get_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
540 static const char *
541 get_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
557 static unsigned int
558 arc_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
600 static int
601 extract_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
645 static bfd_boolean
646 operand_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
665 static void
666 parse_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
704 static void
705 parse_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
728 static enum dis_insn_type
729 arc_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
768 static int
769 print_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
1138 disassembler_ftype
1139 arc_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
1157 struct arcDisState
1158 arcAnalyzeInstr (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
1179 void
1180 print_arc_disassembler_options (FILE *stream)
1181 {
1182   fprintf (stream, _("\n\
1183 The following ARC specific disassembler options are supported for use \n\
1184 with -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:  */