[ARC] Rename "class" named attributes.
[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 "arc-dis.h"
29 #include "arc-ext.h"
30
31
32 /* Globals variables.  */
33
34 static const char * const regnames[64] =
35 {
36   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
37   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
38   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
39   "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
40
41   "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
42   "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
43   "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
44   "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
45 };
46
47 /* Macros section.  */
48
49 #ifdef DEBUG
50 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
51 #else
52 # define pr_debug(fmt, args...)
53 #endif
54
55 #define ARRANGE_ENDIAN(info, buf)                                       \
56   (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf))    \
57    : bfd_getb32 (buf))
58
59 #define BITS(word,s,e)  (((word) << (sizeof (word) * 8 - 1 - e)) >>     \
60                          (s + (sizeof (word) * 8 - 1 - e)))
61 #define OPCODE(word)    (BITS ((word), 27, 31))
62
63 #define OPCODE_AC(word)   (BITS ((word), 11, 15))
64
65 /* Functions implementation.  */
66
67 static bfd_vma
68 bfd_getm32 (unsigned int data)
69 {
70   bfd_vma value = 0;
71
72   value = ((data & 0xff00) | (data & 0xff)) << 16;
73   value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
74   return value;
75 }
76
77 static int
78 special_flag_p (const char *opname,
79                 const char *flgname)
80 {
81   const struct arc_flag_special *flg_spec;
82   unsigned i, j, flgidx;
83
84   for (i = 0; i < arc_num_flag_special; i++)
85     {
86       flg_spec = &arc_flag_special_cases[i];
87
88       if (strcmp (opname, flg_spec->name))
89         continue;
90
91       /* Found potential special case instruction.  */
92       for (j=0;; ++j)
93         {
94           flgidx = flg_spec->flags[j];
95           if (flgidx == 0)
96             break; /* End of the array.  */
97
98           if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
99             return 1;
100         }
101     }
102   return 0;
103 }
104
105 /* Find proper format for the given opcode.  */
106 static const struct arc_opcode *
107 find_format (const struct arc_opcode *arc_table,
108              unsigned *insn, unsigned int insnLen,
109              unsigned isa_mask)
110 {
111   unsigned int i = 0;
112   const struct arc_opcode *opcode = NULL;
113   const unsigned char *opidx;
114   const unsigned char *flgidx;
115
116   do {
117     bfd_boolean invalid = FALSE;
118
119     opcode = &arc_table[i++];
120
121     if (ARC_SHORT (opcode->mask) && (insnLen == 2))
122       {
123         if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
124           continue;
125       }
126     else if (!ARC_SHORT (opcode->mask) && (insnLen == 4))
127       {
128         if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
129           continue;
130       }
131     else
132       continue;
133
134     if ((insn[0] ^ opcode->opcode) & opcode->mask)
135       continue;
136
137     if (!(opcode->cpu & isa_mask))
138       continue;
139
140     /* Possible candidate, check the operands.  */
141     for (opidx = opcode->operands; *opidx; opidx++)
142       {
143         int value;
144         const struct arc_operand *operand = &arc_operands[*opidx];
145
146         if (operand->flags & ARC_OPERAND_FAKE)
147           continue;
148
149         if (operand->extract)
150           value = (*operand->extract) (insn[0], &invalid);
151         else
152           value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
153
154         /* Check for LIMM indicator.  If it is there, then make sure
155            we pick the right format.  */
156         if (operand->flags & ARC_OPERAND_IR
157             && !(operand->flags & ARC_OPERAND_LIMM))
158           {
159             if ((value == 0x3E && insnLen == 4)
160                 || (value == 0x1E && insnLen == 2))
161               {
162                 invalid = TRUE;
163                 break;
164               }
165           }
166       }
167
168     /* Check the flags.  */
169     for (flgidx = opcode->flags; *flgidx; flgidx++)
170       {
171         /* Get a valid flag class.  */
172         const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
173         const unsigned *flgopridx;
174         int foundA = 0, foundB = 0;
175         unsigned int value;
176
177         /* Check first the extensions.  */
178         if (cl_flags->flag_class & F_CLASS_EXTEND)
179           {
180             value = (insn[0] & 0x1F);
181             if (arcExtMap_condCodeName (value))
182               continue;
183           }
184         for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
185           {
186             const struct arc_flag_operand *flg_operand =
187               &arc_flag_operands[*flgopridx];
188
189             value = (insn[0] >> flg_operand->shift)
190               & ((1 << flg_operand->bits) - 1);
191             if (value == flg_operand->code)
192               foundA = 1;
193             if (value)
194               foundB = 1;
195           }
196         if (!foundA && foundB)
197           {
198             invalid = TRUE;
199             break;
200           }
201       }
202
203     if (invalid)
204       continue;
205
206     /* The instruction is valid.  */
207     return opcode;
208   } while (opcode->mask);
209
210   return NULL;
211 }
212
213 static void
214 print_flags (const struct arc_opcode *opcode,
215              unsigned *insn,
216              struct disassemble_info *info)
217 {
218   const unsigned char *flgidx;
219   unsigned int value;
220
221   /* Now extract and print the flags.  */
222   for (flgidx = opcode->flags; *flgidx; flgidx++)
223     {
224       /* Get a valid flag class.  */
225       const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
226       const unsigned *flgopridx;
227
228       /* Check first the extensions.  */
229       if (cl_flags->flag_class & F_CLASS_EXTEND)
230         {
231           const char *name;
232           value = (insn[0] & 0x1F);
233
234           name = arcExtMap_condCodeName (value);
235           if (name)
236             {
237               (*info->fprintf_func) (info->stream, ".%s", name);
238               continue;
239             }
240         }
241
242       for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
243         {
244           const struct arc_flag_operand *flg_operand =
245             &arc_flag_operands[*flgopridx];
246
247           if (!flg_operand->favail)
248             continue;
249
250           value = (insn[0] >> flg_operand->shift)
251             & ((1 << flg_operand->bits) - 1);
252           if (value == flg_operand->code)
253             {
254                /* FIXME!: print correctly nt/t flag.  */
255               if (!special_flag_p (opcode->name, flg_operand->name))
256                 (*info->fprintf_func) (info->stream, ".");
257               else if (info->insn_type == dis_dref)
258                 {
259                   switch (flg_operand->name[0])
260                     {
261                     case 'b':
262                       info->data_size = 1;
263                       break;
264                     case 'h':
265                     case 'w':
266                       info->data_size = 2;
267                       break;
268                     default:
269                       info->data_size = 4;
270                       break;
271                     }
272                 }
273               (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
274             }
275
276           if (flg_operand->name[0] == 'd'
277               && flg_operand->name[1] == 0)
278             info->branch_delay_insns = 1;
279         }
280     }
281 }
282
283 static const char *
284 get_auxreg (const struct arc_opcode *opcode,
285             int value,
286             unsigned isa_mask)
287 {
288   const char *name;
289   unsigned int i;
290   const struct arc_aux_reg *auxr = &arc_aux_regs[0];
291
292   if (opcode->insn_class != AUXREG)
293     return NULL;
294
295   name = arcExtMap_auxRegName (value);
296   if (name)
297     return name;
298
299   for (i = 0; i < arc_num_aux_regs; i++, auxr++)
300     {
301       if (!(auxr->cpu & isa_mask))
302         continue;
303
304       if (auxr->subclass != NONE)
305         return NULL;
306
307       if (auxr->address == value)
308         return auxr->name;
309     }
310   return NULL;
311 }
312
313 /* Calculate the instruction length for an instruction starting with MSB
314    and LSB, the most and least significant byte.  The ISA_MASK is used to
315    filter the instructions considered to only those that are part of the
316    current architecture.
317
318    The instruction lengths are calculated from the ARC_OPCODE table, and
319    cached for later use.  */
320
321 static unsigned int
322 arc_insn_length (bfd_byte msb, struct disassemble_info *info)
323 {
324   bfd_byte major_opcode = msb >> 3;
325
326   switch (info->mach)
327     {
328     case bfd_mach_arc_nps400:
329     case bfd_mach_arc_arc700:
330     case bfd_mach_arc_arc600:
331       return (major_opcode > 0xb) ? 2 : 4;
332       break;
333
334     case bfd_mach_arc_arcv2:
335       return (major_opcode > 0x7) ? 2 : 4;
336       break;
337
338     default:
339       abort ();
340     }
341 }
342
343 /* Disassemble ARC instructions.  */
344
345 static int
346 print_insn_arc (bfd_vma memaddr,
347                 struct disassemble_info *info)
348 {
349   bfd_byte buffer[4];
350   unsigned int lowbyte, highbyte;
351   int status;
352   unsigned int insnLen;
353   unsigned insn[2] = { 0, 0 };
354   unsigned isa_mask;
355   const unsigned char *opidx;
356   const struct arc_opcode *opcode;
357   const extInstruction_t *einsn;
358   bfd_boolean need_comma;
359   bfd_boolean open_braket;
360   int size;
361
362   lowbyte  = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
363   highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
364
365   switch (info->mach)
366     {
367     case bfd_mach_arc_nps400:
368       isa_mask = ARC_OPCODE_ARC700 | ARC_OPCODE_NPS400;
369       break;
370
371     case bfd_mach_arc_arc700:
372       isa_mask = ARC_OPCODE_ARC700;
373       break;
374
375     case bfd_mach_arc_arc600:
376       isa_mask = ARC_OPCODE_ARC600;
377       break;
378
379     case bfd_mach_arc_arcv2:
380     default:
381       isa_mask = ARC_OPCODE_ARCv2HS | ARC_OPCODE_ARCv2EM;
382       break;
383     }
384
385   /* This variable may be set by the instruction decoder.  It suggests
386      the number of bytes objdump should display on a single line.  If
387      the instruction decoder sets this, it should always set it to
388      the same value in order to get reasonable looking output.  */
389
390   info->bytes_per_line  = 8;
391
392   /* In the next lines, we set two info variables control the way
393      objdump displays the raw data.  For example, if bytes_per_line is
394      8 and bytes_per_chunk is 4, the output will look like this:
395      00:   00000000 00000000
396      with the chunks displayed according to "display_endian".  */
397
398   if (info->section
399       && !(info->section->flags & SEC_CODE))
400     {
401       /* This is not a CODE section.  */
402       switch (info->section->size)
403         {
404         case 1:
405         case 2:
406         case 4:
407           size = info->section->size;
408           break;
409         default:
410           size = (info->section->size & 0x01) ? 1 : 4;
411           break;
412         }
413       info->bytes_per_chunk = 1;
414       info->display_endian = info->endian;
415     }
416   else
417     {
418       size = 2;
419       info->bytes_per_chunk = 2;
420       info->display_endian = info->endian;
421     }
422
423   /* Read the insn into a host word.  */
424   status = (*info->read_memory_func) (memaddr, buffer, size, info);
425   if (status != 0)
426     {
427       (*info->memory_error_func) (status, memaddr, info);
428       return -1;
429     }
430
431   if (info->section
432       && !(info->section->flags & SEC_CODE))
433     {
434       /* Data section.  */
435       unsigned long data;
436
437       data = bfd_get_bits (buffer, size * 8,
438                            info->display_endian == BFD_ENDIAN_BIG);
439       switch (size)
440         {
441         case 1:
442           (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
443           break;
444         case 2:
445           (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
446           break;
447         case 4:
448           (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
449           break;
450         default:
451           abort ();
452         }
453       return size;
454     }
455
456   insnLen = arc_insn_length (buffer[lowbyte], info);
457   switch (insnLen)
458     {
459     case 2:
460       insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
461       break;
462
463     default:
464       /* An unknown instruction is treated as being length 4.  This is
465          possibly not the best solution, but matches the behaviour that was
466          in place before the table based instruction length look-up was
467          introduced.  */
468     case 4:
469       /* This is a long instruction: Read the remaning 2 bytes.  */
470       status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
471       if (status != 0)
472         {
473           (*info->memory_error_func) (status, memaddr + 2, info);
474           return -1;
475         }
476       insn[0] = ARRANGE_ENDIAN (info, buffer);
477       break;
478     }
479
480   /* Set some defaults for the insn info.  */
481   info->insn_info_valid    = 1;
482   info->branch_delay_insns = 0;
483   info->data_size          = 0;
484   info->insn_type          = dis_nonbranch;
485   info->target             = 0;
486   info->target2            = 0;
487
488   /* FIXME to be moved in dissasemble_init_for_target.  */
489   info->disassembler_needs_relocs = TRUE;
490
491   /* Find the first match in the opcode table.  */
492   opcode = find_format (arc_opcodes, insn, insnLen, isa_mask);
493
494   if (!opcode)
495     {
496       /* No instruction found.  Try the extensions.  */
497       einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]);
498       if (einsn)
499         {
500           const char *errmsg = NULL;
501           opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg);
502           if (opcode == NULL)
503             {
504               (*info->fprintf_func) (info->stream,
505                                      "An error occured while "
506                                      "generating the extension instruction "
507                                      "operations");
508               return -1;
509             }
510
511           opcode = find_format (opcode, insn, insnLen, isa_mask);
512           assert (opcode != NULL);
513         }
514       else
515         {
516           if (insnLen == 2)
517             (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
518           else
519             (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
520
521           info->insn_type = dis_noninsn;
522           return insnLen;
523         }
524     }
525
526   /* Print the mnemonic.  */
527   (*info->fprintf_func) (info->stream, "%s", opcode->name);
528
529   /* Preselect the insn class.  */
530   switch (opcode->insn_class)
531     {
532     case BRANCH:
533     case JUMP:
534       if (!strncmp (opcode->name, "bl", 2)
535           || !strncmp (opcode->name, "jl", 2))
536         info->insn_type = dis_jsr;
537       else
538         info->insn_type = dis_branch;
539       break;
540     case MEMORY:
541       info->insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */
542       break;
543     default:
544       info->insn_type = dis_nonbranch;
545       break;
546     }
547
548   pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
549
550   print_flags (opcode, insn, info);
551
552   if (opcode->operands[0] != 0)
553     (*info->fprintf_func) (info->stream, "\t");
554
555   need_comma = FALSE;
556   open_braket = FALSE;
557
558   /* Now extract and print the operands.  */
559   for (opidx = opcode->operands; *opidx; opidx++)
560     {
561       const struct arc_operand *operand = &arc_operands[*opidx];
562       int value;
563
564       if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
565         {
566           (*info->fprintf_func) (info->stream, "]");
567           open_braket = FALSE;
568           continue;
569         }
570
571       /* Only take input from real operands.  */
572       if ((operand->flags & ARC_OPERAND_FAKE)
573           && !(operand->flags & ARC_OPERAND_BRAKET))
574         continue;
575
576       if (operand->extract)
577         value = (*operand->extract) (insn[0], (int *) NULL);
578       else
579         {
580           if (operand->flags & ARC_OPERAND_ALIGNED32)
581             {
582               value = (insn[0] >> operand->shift)
583                 & ((1 << (operand->bits - 2)) - 1);
584               value = value << 2;
585             }
586           else
587             {
588               value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
589             }
590           if (operand->flags & ARC_OPERAND_SIGNED)
591             {
592               int signbit = 1 << (operand->bits - 1);
593               value = (value ^ signbit) - signbit;
594             }
595         }
596
597       if (operand->flags & ARC_OPERAND_IGNORE
598           && (operand->flags & ARC_OPERAND_IR
599               && value == -1))
600         continue;
601
602       if (need_comma)
603         (*info->fprintf_func) (info->stream, ",");
604
605       if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
606         {
607           (*info->fprintf_func) (info->stream, "[");
608           open_braket = TRUE;
609           need_comma = FALSE;
610           continue;
611         }
612
613       /* Read the limm operand, if required.  */
614       if (operand->flags & ARC_OPERAND_LIMM
615           && !(operand->flags & ARC_OPERAND_DUPLICATE))
616         {
617           status = (*info->read_memory_func) (memaddr + insnLen, buffer,
618                                               4, info);
619           if (status != 0)
620             {
621               (*info->memory_error_func) (status, memaddr + insnLen, info);
622               return -1;
623             }
624           insn[1] = ARRANGE_ENDIAN (info, buffer);
625         }
626
627       /* Print the operand as directed by the flags.  */
628       if (operand->flags & ARC_OPERAND_IR)
629         {
630           const char *rname;
631
632           assert (value >=0 && value < 64);
633           rname = arcExtMap_coreRegName (value);
634           if (!rname)
635             rname = regnames[value];
636           (*info->fprintf_func) (info->stream, "%s", rname);
637           if (operand->flags & ARC_OPERAND_TRUNCATE)
638             {
639               rname = arcExtMap_coreRegName (value + 1);
640               if (!rname)
641                 rname = regnames[value + 1];
642               (*info->fprintf_func) (info->stream, "%s", rname);
643             }
644         }
645       else if (operand->flags & ARC_OPERAND_LIMM)
646         {
647           const char *rname = get_auxreg (opcode, insn[1], isa_mask);
648           if (rname && open_braket)
649             (*info->fprintf_func) (info->stream, "%s", rname);
650           else
651             {
652               (*info->fprintf_func) (info->stream, "%#x", insn[1]);
653               if (info->insn_type == dis_branch
654                   || info->insn_type == dis_jsr)
655                 info->target = (bfd_vma) insn[1];
656             }
657         }
658       else if (operand->flags & ARC_OPERAND_PCREL)
659         {
660            /* PCL relative.  */
661           if (info->flags & INSN_HAS_RELOC)
662             memaddr = 0;
663           (*info->print_address_func) ((memaddr & ~3) + value, info);
664
665           info->target = (bfd_vma) (memaddr & ~3) + value;
666         }
667       else if (operand->flags & ARC_OPERAND_SIGNED)
668         {
669           const char *rname = get_auxreg (opcode, value, isa_mask);
670           if (rname && open_braket)
671             (*info->fprintf_func) (info->stream, "%s", rname);
672           else
673             (*info->fprintf_func) (info->stream, "%d", value);
674         }
675       else
676         {
677           if (operand->flags & ARC_OPERAND_TRUNCATE
678               && !(operand->flags & ARC_OPERAND_ALIGNED32)
679               && !(operand->flags & ARC_OPERAND_ALIGNED16)
680               && value > 0 && value <= 14)
681             (*info->fprintf_func) (info->stream, "r13-%s",
682                                    regnames[13 + value - 1]);
683           else
684             {
685               const char *rname = get_auxreg (opcode, value, isa_mask);
686               if (rname && open_braket)
687                 (*info->fprintf_func) (info->stream, "%s", rname);
688               else
689                 (*info->fprintf_func) (info->stream, "%#x", value);
690             }
691         }
692
693       need_comma = TRUE;
694
695       /* Adjust insn len.  */
696       if (operand->flags & ARC_OPERAND_LIMM
697           && !(operand->flags & ARC_OPERAND_DUPLICATE))
698         insnLen += 4;
699     }
700
701   return insnLen;
702 }
703
704
705 disassembler_ftype
706 arc_get_disassembler (bfd *abfd)
707 {
708   /* Read the extenssion insns and registers, if any.  */
709   build_ARC_extmap (abfd);
710 #ifdef DEBUG
711   dump_ARC_extmap ();
712 #endif
713
714   return print_insn_arc;
715 }
716
717 /* Disassemble ARC instructions.  Used by debugger.  */
718
719 struct arcDisState
720 arcAnalyzeInstr (bfd_vma memaddr,
721                  struct disassemble_info *info)
722 {
723   struct arcDisState ret;
724   memset (&ret, 0, sizeof (struct arcDisState));
725
726   ret.instructionLen = print_insn_arc (memaddr, info);
727
728 #if 0
729   ret.words[0] = insn[0];
730   ret.words[1] = insn[1];
731   ret._this = &ret;
732   ret.coreRegName = _coreRegName;
733   ret.auxRegName = _auxRegName;
734   ret.condCodeName = _condCodeName;
735   ret.instName = _instName;
736 #endif
737
738   return ret;
739 }
740
741 /* Local variables:
742    eval: (c-set-style "gnu")
743    indent-tabs-mode: t
744    End:  */