[ARC] Update instruction type and delay slot info.
[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               if (flg_operand->name[0] == 'd'
274                   && flg_operand->name[1] == 0)
275                 info->branch_delay_insns = 1;
276
277               /* Check if it is a conditional flag.  */
278               if (cl_flags->flag_class & F_CLASS_COND)
279                 {
280                   if (info->insn_type == dis_jsr)
281                     info->insn_type = dis_condjsr;
282                   else if (info->insn_type == dis_branch)
283                     info->insn_type = dis_condbranch;
284                 }
285
286               (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
287             }
288         }
289     }
290 }
291
292 static const char *
293 get_auxreg (const struct arc_opcode *opcode,
294             int value,
295             unsigned isa_mask)
296 {
297   const char *name;
298   unsigned int i;
299   const struct arc_aux_reg *auxr = &arc_aux_regs[0];
300
301   if (opcode->insn_class != AUXREG)
302     return NULL;
303
304   name = arcExtMap_auxRegName (value);
305   if (name)
306     return name;
307
308   for (i = 0; i < arc_num_aux_regs; i++, auxr++)
309     {
310       if (!(auxr->cpu & isa_mask))
311         continue;
312
313       if (auxr->subclass != NONE)
314         return NULL;
315
316       if (auxr->address == value)
317         return auxr->name;
318     }
319   return NULL;
320 }
321
322 /* Calculate the instruction length for an instruction starting with MSB
323    and LSB, the most and least significant byte.  The ISA_MASK is used to
324    filter the instructions considered to only those that are part of the
325    current architecture.
326
327    The instruction lengths are calculated from the ARC_OPCODE table, and
328    cached for later use.  */
329
330 static unsigned int
331 arc_insn_length (bfd_byte msb, struct disassemble_info *info)
332 {
333   bfd_byte major_opcode = msb >> 3;
334
335   switch (info->mach)
336     {
337     case bfd_mach_arc_nps400:
338     case bfd_mach_arc_arc700:
339     case bfd_mach_arc_arc600:
340       return (major_opcode > 0xb) ? 2 : 4;
341       break;
342
343     case bfd_mach_arc_arcv2:
344       return (major_opcode > 0x7) ? 2 : 4;
345       break;
346
347     default:
348       abort ();
349     }
350 }
351
352 /* Disassemble ARC instructions.  */
353
354 static int
355 print_insn_arc (bfd_vma memaddr,
356                 struct disassemble_info *info)
357 {
358   bfd_byte buffer[4];
359   unsigned int lowbyte, highbyte;
360   int status;
361   unsigned int insnLen;
362   unsigned insn[2] = { 0, 0 };
363   unsigned isa_mask;
364   const unsigned char *opidx;
365   const struct arc_opcode *opcode;
366   const extInstruction_t *einsn;
367   bfd_boolean need_comma;
368   bfd_boolean open_braket;
369   int size;
370
371   lowbyte  = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
372   highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
373
374   switch (info->mach)
375     {
376     case bfd_mach_arc_nps400:
377       isa_mask = ARC_OPCODE_ARC700 | ARC_OPCODE_NPS400;
378       break;
379
380     case bfd_mach_arc_arc700:
381       isa_mask = ARC_OPCODE_ARC700;
382       break;
383
384     case bfd_mach_arc_arc600:
385       isa_mask = ARC_OPCODE_ARC600;
386       break;
387
388     case bfd_mach_arc_arcv2:
389     default:
390       isa_mask = ARC_OPCODE_ARCv2HS | ARC_OPCODE_ARCv2EM;
391       break;
392     }
393
394   /* This variable may be set by the instruction decoder.  It suggests
395      the number of bytes objdump should display on a single line.  If
396      the instruction decoder sets this, it should always set it to
397      the same value in order to get reasonable looking output.  */
398
399   info->bytes_per_line  = 8;
400
401   /* In the next lines, we set two info variables control the way
402      objdump displays the raw data.  For example, if bytes_per_line is
403      8 and bytes_per_chunk is 4, the output will look like this:
404      00:   00000000 00000000
405      with the chunks displayed according to "display_endian".  */
406
407   if (info->section
408       && !(info->section->flags & SEC_CODE))
409     {
410       /* This is not a CODE section.  */
411       switch (info->section->size)
412         {
413         case 1:
414         case 2:
415         case 4:
416           size = info->section->size;
417           break;
418         default:
419           size = (info->section->size & 0x01) ? 1 : 4;
420           break;
421         }
422       info->bytes_per_chunk = 1;
423       info->display_endian = info->endian;
424     }
425   else
426     {
427       size = 2;
428       info->bytes_per_chunk = 2;
429       info->display_endian = info->endian;
430     }
431
432   /* Read the insn into a host word.  */
433   status = (*info->read_memory_func) (memaddr, buffer, size, info);
434   if (status != 0)
435     {
436       (*info->memory_error_func) (status, memaddr, info);
437       return -1;
438     }
439
440   if (info->section
441       && !(info->section->flags & SEC_CODE))
442     {
443       /* Data section.  */
444       unsigned long data;
445
446       data = bfd_get_bits (buffer, size * 8,
447                            info->display_endian == BFD_ENDIAN_BIG);
448       switch (size)
449         {
450         case 1:
451           (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
452           break;
453         case 2:
454           (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
455           break;
456         case 4:
457           (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
458           break;
459         default:
460           abort ();
461         }
462       return size;
463     }
464
465   insnLen = arc_insn_length (buffer[lowbyte], info);
466   switch (insnLen)
467     {
468     case 2:
469       insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
470       break;
471
472     default:
473       /* An unknown instruction is treated as being length 4.  This is
474          possibly not the best solution, but matches the behaviour that was
475          in place before the table based instruction length look-up was
476          introduced.  */
477     case 4:
478       /* This is a long instruction: Read the remaning 2 bytes.  */
479       status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
480       if (status != 0)
481         {
482           (*info->memory_error_func) (status, memaddr + 2, info);
483           return -1;
484         }
485       insn[0] = ARRANGE_ENDIAN (info, buffer);
486       break;
487     }
488
489   /* Set some defaults for the insn info.  */
490   info->insn_info_valid    = 1;
491   info->branch_delay_insns = 0;
492   info->data_size          = 0;
493   info->insn_type          = dis_nonbranch;
494   info->target             = 0;
495   info->target2            = 0;
496
497   /* FIXME to be moved in dissasemble_init_for_target.  */
498   info->disassembler_needs_relocs = TRUE;
499
500   /* Find the first match in the opcode table.  */
501   opcode = find_format (arc_opcodes, insn, insnLen, isa_mask);
502
503   if (!opcode)
504     {
505       /* No instruction found.  Try the extensions.  */
506       einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]);
507       if (einsn)
508         {
509           const char *errmsg = NULL;
510           opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg);
511           if (opcode == NULL)
512             {
513               (*info->fprintf_func) (info->stream,
514                                      "An error occured while "
515                                      "generating the extension instruction "
516                                      "operations");
517               return -1;
518             }
519
520           opcode = find_format (opcode, insn, insnLen, isa_mask);
521           assert (opcode != NULL);
522         }
523       else
524         {
525           if (insnLen == 2)
526             (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
527           else
528             (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
529
530           info->insn_type = dis_noninsn;
531           return insnLen;
532         }
533     }
534
535   /* Print the mnemonic.  */
536   (*info->fprintf_func) (info->stream, "%s", opcode->name);
537
538   /* Preselect the insn class.  */
539   switch (opcode->insn_class)
540     {
541     case BRANCH:
542     case JUMP:
543       if (!strncmp (opcode->name, "bl", 2)
544           || !strncmp (opcode->name, "jl", 2))
545         {
546           if (opcode->subclass == COND)
547             info->insn_type = dis_condjsr;
548           else
549             info->insn_type = dis_jsr;
550         }
551       else
552         {
553           if (opcode->subclass == COND)
554             info->insn_type = dis_condbranch;
555           else
556             info->insn_type = dis_branch;
557         }
558       break;
559     case MEMORY:
560       info->insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */
561       break;
562     default:
563       info->insn_type = dis_nonbranch;
564       break;
565     }
566
567   pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
568
569   print_flags (opcode, insn, info);
570
571   if (opcode->operands[0] != 0)
572     (*info->fprintf_func) (info->stream, "\t");
573
574   need_comma = FALSE;
575   open_braket = FALSE;
576
577   /* Now extract and print the operands.  */
578   for (opidx = opcode->operands; *opidx; opidx++)
579     {
580       const struct arc_operand *operand = &arc_operands[*opidx];
581       int value;
582
583       if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
584         {
585           (*info->fprintf_func) (info->stream, "]");
586           open_braket = FALSE;
587           continue;
588         }
589
590       /* Only take input from real operands.  */
591       if ((operand->flags & ARC_OPERAND_FAKE)
592           && !(operand->flags & ARC_OPERAND_BRAKET))
593         continue;
594
595       if (operand->extract)
596         value = (*operand->extract) (insn[0], (int *) NULL);
597       else
598         {
599           if (operand->flags & ARC_OPERAND_ALIGNED32)
600             {
601               value = (insn[0] >> operand->shift)
602                 & ((1 << (operand->bits - 2)) - 1);
603               value = value << 2;
604             }
605           else
606             {
607               value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
608             }
609           if (operand->flags & ARC_OPERAND_SIGNED)
610             {
611               int signbit = 1 << (operand->bits - 1);
612               value = (value ^ signbit) - signbit;
613             }
614         }
615
616       if (operand->flags & ARC_OPERAND_IGNORE
617           && (operand->flags & ARC_OPERAND_IR
618               && value == -1))
619         continue;
620
621       if (need_comma)
622         (*info->fprintf_func) (info->stream, ",");
623
624       if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
625         {
626           (*info->fprintf_func) (info->stream, "[");
627           open_braket = TRUE;
628           need_comma = FALSE;
629           continue;
630         }
631
632       /* Read the limm operand, if required.  */
633       if (operand->flags & ARC_OPERAND_LIMM
634           && !(operand->flags & ARC_OPERAND_DUPLICATE))
635         {
636           status = (*info->read_memory_func) (memaddr + insnLen, buffer,
637                                               4, info);
638           if (status != 0)
639             {
640               (*info->memory_error_func) (status, memaddr + insnLen, info);
641               return -1;
642             }
643           insn[1] = ARRANGE_ENDIAN (info, buffer);
644         }
645
646       /* Print the operand as directed by the flags.  */
647       if (operand->flags & ARC_OPERAND_IR)
648         {
649           const char *rname;
650
651           assert (value >=0 && value < 64);
652           rname = arcExtMap_coreRegName (value);
653           if (!rname)
654             rname = regnames[value];
655           (*info->fprintf_func) (info->stream, "%s", rname);
656           if (operand->flags & ARC_OPERAND_TRUNCATE)
657             {
658               rname = arcExtMap_coreRegName (value + 1);
659               if (!rname)
660                 rname = regnames[value + 1];
661               (*info->fprintf_func) (info->stream, "%s", rname);
662             }
663         }
664       else if (operand->flags & ARC_OPERAND_LIMM)
665         {
666           const char *rname = get_auxreg (opcode, insn[1], isa_mask);
667           if (rname && open_braket)
668             (*info->fprintf_func) (info->stream, "%s", rname);
669           else
670             {
671               (*info->fprintf_func) (info->stream, "%#x", insn[1]);
672               if (info->insn_type == dis_branch
673                   || info->insn_type == dis_jsr)
674                 info->target = (bfd_vma) insn[1];
675             }
676         }
677       else if (operand->flags & ARC_OPERAND_PCREL)
678         {
679            /* PCL relative.  */
680           if (info->flags & INSN_HAS_RELOC)
681             memaddr = 0;
682           (*info->print_address_func) ((memaddr & ~3) + value, info);
683
684           info->target = (bfd_vma) (memaddr & ~3) + value;
685         }
686       else if (operand->flags & ARC_OPERAND_SIGNED)
687         {
688           const char *rname = get_auxreg (opcode, value, isa_mask);
689           if (rname && open_braket)
690             (*info->fprintf_func) (info->stream, "%s", rname);
691           else
692             (*info->fprintf_func) (info->stream, "%d", value);
693         }
694       else
695         {
696           if (operand->flags & ARC_OPERAND_TRUNCATE
697               && !(operand->flags & ARC_OPERAND_ALIGNED32)
698               && !(operand->flags & ARC_OPERAND_ALIGNED16)
699               && value > 0 && value <= 14)
700             (*info->fprintf_func) (info->stream, "r13-%s",
701                                    regnames[13 + value - 1]);
702           else
703             {
704               const char *rname = get_auxreg (opcode, value, isa_mask);
705               if (rname && open_braket)
706                 (*info->fprintf_func) (info->stream, "%s", rname);
707               else
708                 (*info->fprintf_func) (info->stream, "%#x", value);
709             }
710         }
711
712       need_comma = TRUE;
713
714       /* Adjust insn len.  */
715       if (operand->flags & ARC_OPERAND_LIMM
716           && !(operand->flags & ARC_OPERAND_DUPLICATE))
717         insnLen += 4;
718     }
719
720   return insnLen;
721 }
722
723
724 disassembler_ftype
725 arc_get_disassembler (bfd *abfd)
726 {
727   /* Read the extenssion insns and registers, if any.  */
728   build_ARC_extmap (abfd);
729 #ifdef DEBUG
730   dump_ARC_extmap ();
731 #endif
732
733   return print_insn_arc;
734 }
735
736 /* Disassemble ARC instructions.  Used by debugger.  */
737
738 struct arcDisState
739 arcAnalyzeInstr (bfd_vma memaddr,
740                  struct disassemble_info *info)
741 {
742   struct arcDisState ret;
743   memset (&ret, 0, sizeof (struct arcDisState));
744
745   ret.instructionLen = print_insn_arc (memaddr, info);
746
747 #if 0
748   ret.words[0] = insn[0];
749   ret.words[1] = insn[1];
750   ret._this = &ret;
751   ret.coreRegName = _coreRegName;
752   ret.auxRegName = _auxRegName;
753   ret.condCodeName = _condCodeName;
754   ret.instName = _instName;
755 #endif
756
757   return ret;
758 }
759
760 /* Local variables:
761    eval: (c-set-style "gnu")
762    indent-tabs-mode: t
763    End:  */