[ARM] Add ARMv8.2 FP16 vmul/vmla/vmls (by scalar)
[external/binutils.git] / opcodes / arc-ext.c
1 /* ARC target-dependent stuff.  Extension structure access functions
2    Copyright (C) 1995-2016 Free Software Foundation, Inc.
3
4    This file is part of libopcodes.
5
6    This library is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10
11    It is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20
21 #include "sysdep.h"
22 #include <stdlib.h>
23 #include <stdio.h>
24
25 #include "bfd.h"
26 #include "arc-ext.h"
27 #include "elf/arc.h"
28 #include "libiberty.h"
29
30
31 /* This module provides support for extensions to the ARC processor
32    architecture.  */
33
34
35 /* Local constants.  */
36
37 #define FIRST_EXTENSION_CORE_REGISTER   32
38 #define LAST_EXTENSION_CORE_REGISTER    59
39 #define FIRST_EXTENSION_CONDITION_CODE  0x10
40 #define LAST_EXTENSION_CONDITION_CODE   0x1f
41
42 #define NUM_EXT_CORE      \
43   (LAST_EXTENSION_CORE_REGISTER  - FIRST_EXTENSION_CORE_REGISTER  + 1)
44 #define NUM_EXT_COND      \
45   (LAST_EXTENSION_CONDITION_CODE - FIRST_EXTENSION_CONDITION_CODE + 1)
46 #define INST_HASH_BITS    6
47 #define INST_HASH_SIZE    (1 << INST_HASH_BITS)
48 #define INST_HASH_MASK    (INST_HASH_SIZE - 1)
49
50
51 /* Local types.  */
52
53 /* These types define the information stored in the table.  */
54
55 struct ExtInstruction
56 {
57   char                   major;
58   char                   minor;
59   char                   flags;
60   char*                  name;
61   struct ExtInstruction* next;
62 };
63
64 struct ExtAuxRegister
65 {
66   long                   address;
67   char*                  name;
68   struct ExtAuxRegister* next;
69 };
70
71 struct ExtCoreRegister
72 {
73   short             number;
74   enum ExtReadWrite rw;
75   char*             name;
76 };
77
78 struct arcExtMap
79 {
80   struct ExtAuxRegister* auxRegisters;
81   struct ExtInstruction* instructions[INST_HASH_SIZE];
82   struct ExtCoreRegister coreRegisters[NUM_EXT_CORE];
83   char*                  condCodes[NUM_EXT_COND];
84 };
85
86
87 /* Local data.  */
88
89 /* Extension table.  */
90 static struct arcExtMap arc_extension_map;
91
92
93 /* Local macros.  */
94
95 /* A hash function used to map instructions into the table.  */
96 #define INST_HASH(MAJOR, MINOR)    ((((MAJOR) << 3) ^ (MINOR)) & INST_HASH_MASK)
97
98
99 /* Local functions.  */
100
101 static void
102 create_map (unsigned char *block,
103             unsigned long length)
104 {
105   unsigned char *p = block;
106
107   while (p && p < (block + length))
108     {
109       /* p[0] == length of record
110          p[1] == type of record
111          For instructions:
112            p[2]  = opcode
113            p[3]  = minor opcode (if opcode == 3)
114            p[4]  = flags
115            p[5]+ = name
116          For core regs and condition codes:
117            p[2]  = value
118            p[3]+ = name
119          For auxiliary regs:
120            p[2..5] = value
121            p[6]+   = name
122              (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]).  */
123
124       /* The sequence of records is temrinated by an "empty"
125          record.  */
126       if (p[0] == 0)
127         break;
128
129       switch (p[1])
130         {
131         case EXT_INSTRUCTION:
132           {
133             struct ExtInstruction  *insn = XNEW (struct ExtInstruction);
134             int                     major = p[2];
135             int                     minor = p[3];
136             struct ExtInstruction **bucket =
137                    &arc_extension_map.instructions[INST_HASH (major, minor)];
138
139             insn->name  = xstrdup ((char *) (p + 5));
140             insn->major = major;
141             insn->minor = minor;
142             insn->flags = p[4];
143             insn->next  = *bucket;
144             *bucket = insn;
145             break;
146           }
147
148         case EXT_CORE_REGISTER:
149           {
150             unsigned char number = p[2];
151             char*         name   = (char *) (p + 3);
152
153             arc_extension_map.
154               coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
155               = number;
156             arc_extension_map.
157               coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
158               = REG_READWRITE;
159             arc_extension_map.
160               coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
161               = xstrdup (name);
162             break;
163           }
164
165         case EXT_LONG_CORE_REGISTER:
166           {
167             unsigned char     number = p[2];
168             char*             name   = (char *) (p + 7);
169             enum ExtReadWrite rw     = p[6];
170
171             arc_extension_map.
172               coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
173               = number;
174             arc_extension_map.
175               coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
176               = rw;
177             arc_extension_map.
178               coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
179               = xstrdup (name);
180           }
181
182         case EXT_COND_CODE:
183           {
184             char *cc_name = xstrdup ((char *) (p + 3));
185
186             arc_extension_map.
187               condCodes[p[2] - FIRST_EXTENSION_CONDITION_CODE]
188               = cc_name;
189             break;
190           }
191
192         case EXT_AUX_REGISTER:
193           {
194             /* Trickier -- need to store linked list of these.  */
195             struct ExtAuxRegister *newAuxRegister
196               = XNEW (struct ExtAuxRegister);
197             char *aux_name = xstrdup ((char *) (p + 6));
198
199             newAuxRegister->name = aux_name;
200             newAuxRegister->address = (p[2] << 24) | (p[3] << 16)
201               | (p[4] << 8) | p[5];
202             newAuxRegister->next = arc_extension_map.auxRegisters;
203             arc_extension_map.auxRegisters = newAuxRegister;
204             break;
205           }
206
207         default:
208           break;
209         }
210
211       p += p[0]; /* Move on to next record.  */
212     }
213 }
214
215
216 /* Free memory that has been allocated for the extensions.  */
217
218 static void
219 destroy_map (void)
220 {
221   struct ExtAuxRegister *r;
222   unsigned int           i;
223
224   /* Free auxiliary registers.  */
225   r = arc_extension_map.auxRegisters;
226   while (r)
227     {
228       /* N.B. after r has been freed, r->next is invalid!  */
229       struct ExtAuxRegister* next = r->next;
230
231       free (r->name);
232       free (r);
233       r = next;
234     }
235
236   /* Free instructions.  */
237   for (i = 0; i < INST_HASH_SIZE; i++)
238     {
239       struct ExtInstruction *insn = arc_extension_map.instructions[i];
240
241       while (insn)
242         {
243           /* N.B. after insn has been freed, insn->next is invalid!  */
244           struct ExtInstruction *next = insn->next;
245
246           free (insn->name);
247           free (insn);
248           insn = next;
249         }
250     }
251
252   /* Free core registers.  */
253   for (i = 0; i < NUM_EXT_CORE; i++)
254     {
255       if (arc_extension_map.coreRegisters[i].name)
256         free (arc_extension_map.coreRegisters[i].name);
257     }
258
259   /* Free condition codes.  */
260   for (i = 0; i < NUM_EXT_COND; i++)
261     {
262       if (arc_extension_map.condCodes[i])
263         free (arc_extension_map.condCodes[i]);
264     }
265
266   memset (&arc_extension_map, 0, sizeof (arc_extension_map));
267 }
268
269
270 static const char *
271 ExtReadWrite_image (enum ExtReadWrite val)
272 {
273     switch (val)
274     {
275         case REG_INVALID  : return "INVALID";
276         case REG_READ     : return "RO";
277         case REG_WRITE    : return "WO";
278         case REG_READWRITE: return "R/W";
279         default           : return "???";
280     }
281 }
282
283
284 /* Externally visible functions.  */
285
286 /* Get the name of an extension instruction.  */
287
288 const char *
289 arcExtMap_instName (int opcode,
290                     int insn,
291                     int *flags)
292 {
293   /* Here the following tasks need to be done.  First of all, the
294      opcode stored in the Extension Map is the real opcode.  However,
295      the subopcode stored in the instruction to be disassembled is
296      mangled.  We pass (in minor opcode), the instruction word.  Here
297      we will un-mangle it and get the real subopcode which we can look
298      for in the Extension Map.  This function is used both for the
299      ARCTangent and the ARCompact, so we would also need some sort of
300      a way to distinguish between the two architectures.  This is
301      because the ARCTangent does not do any of this mangling so we
302      have no issues there.  */
303
304   /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI.  If it is 1
305      then use iiiiIi.  Now, if P is 3 then check M[5:5] and if it is 0
306      then un-mangle using iiiiiI else iiiiii.  */
307
308   unsigned char minor;
309   struct ExtInstruction *temp;
310
311   /* 16-bit instructions.  */
312   if (0x08 <= opcode && opcode <= 0x0b)
313     {
314       unsigned char b, c, i;
315
316       b = (insn & 0x0700) >> 8;
317       c = (insn & 0x00e0) >> 5;
318       i = (insn & 0x001f);
319
320       if (i)
321         minor = i;
322       else
323         minor = (c == 0x07) ? b : c;
324     }
325   /* 32-bit instructions.  */
326   else
327     {
328       unsigned char I, A, B;
329
330       I = (insn & 0x003f0000) >> 16;
331       A = (insn & 0x0000003f);
332       B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
333
334       if (I != 0x2f)
335         {
336 #ifndef UNMANGLED
337           switch (P)
338             {
339             case 3:
340               if (M)
341                 {
342                   minor = I;
343                   break;
344                 }
345             case 0:
346             case 2:
347               minor = (I >> 1) | ((I & 0x1) << 5);
348               break;
349             case 1:
350               minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4);
351             }
352 #else
353           minor = I;
354 #endif
355         }
356       else
357         {
358           if (A != 0x3f)
359             minor = A;
360           else
361             minor = B;
362         }
363     }
364
365   temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
366   while (temp)
367     {
368       if ((temp->major == opcode) && (temp->minor == minor))
369         {
370           *flags = temp->flags;
371           return temp->name;
372         }
373       temp = temp->next;
374     }
375
376   return NULL;
377 }
378
379 /* Get the name of an extension core register.  */
380
381 const char *
382 arcExtMap_coreRegName (int regnum)
383 {
384   if (regnum < FIRST_EXTENSION_CORE_REGISTER
385       || regnum > LAST_EXTENSION_CONDITION_CODE)
386     return NULL;
387   return arc_extension_map.
388     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name;
389 }
390
391 /* Get the access mode of an extension core register.  */
392
393 enum ExtReadWrite
394 arcExtMap_coreReadWrite (int regnum)
395 {
396   if (regnum < FIRST_EXTENSION_CORE_REGISTER
397       || regnum > LAST_EXTENSION_CONDITION_CODE)
398     return REG_INVALID;
399   return arc_extension_map.
400     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw;
401 }
402
403 /* Get the name of an extension condition code.  */
404
405 const char *
406 arcExtMap_condCodeName (int code)
407 {
408   if (code < FIRST_EXTENSION_CONDITION_CODE
409       || code > LAST_EXTENSION_CONDITION_CODE)
410     return NULL;
411   return arc_extension_map.
412     condCodes[code - FIRST_EXTENSION_CONDITION_CODE];
413 }
414
415 /* Get the name of an extension auxiliary register.  */
416
417 const char *
418 arcExtMap_auxRegName (long address)
419 {
420   /* Walk the list of auxiliary register names and find the name.  */
421   struct ExtAuxRegister *r;
422
423   for (r = arc_extension_map.auxRegisters; r; r = r->next)
424     {
425       if (r->address == address)
426         return (const char *)r->name;
427     }
428   return NULL;
429 }
430
431 /* Load extensions described in .arcextmap and
432    .gnu.linkonce.arcextmap.* ELF section.  */
433
434 void
435 build_ARC_extmap (bfd *text_bfd)
436 {
437   asection *sect;
438
439   /* The map is built each time gdb loads an executable file - so free
440      any existing map, as the map defined by the new file may differ
441      from the old.  */
442   destroy_map ();
443
444   for (sect = text_bfd->sections; sect != NULL; sect = sect->next)
445     if (!strncmp (sect->name,
446                   ".gnu.linkonce.arcextmap.",
447           sizeof (".gnu.linkonce.arcextmap.") - 1)
448         || !strcmp (sect->name,".arcextmap"))
449       {
450         bfd_size_type  count  = bfd_get_section_size (sect);
451         unsigned char* buffer = xmalloc (count);
452
453         if (buffer)
454           {
455             if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count))
456               create_map (buffer, count);
457             free (buffer);
458           }
459       }
460 }
461
462
463 void
464 dump_ARC_extmap (void)
465 {
466     struct ExtAuxRegister *r;
467     int                    i;
468
469     r = arc_extension_map.auxRegisters;
470
471     while (r)
472     {
473         printf ("AUX : %s %ld\n", r->name, r->address);
474         r = r->next;
475     }
476
477     for (i = 0; i < INST_HASH_SIZE; i++)
478     {
479         struct ExtInstruction *insn;
480
481         for (insn = arc_extension_map.instructions[i];
482              insn != NULL; insn = insn->next)
483             printf ("INST: %d %d %x %s\n", insn->major, insn->minor,
484                     insn->flags, insn->name);
485     }
486
487     for (i = 0; i < NUM_EXT_CORE; i++)
488     {
489         struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
490
491         if (reg.name)
492             printf ("CORE: %s %d %s\n", reg.name, reg.number,
493                     ExtReadWrite_image (reg.rw));
494     }
495
496     for (i = 0; i < NUM_EXT_COND; i++)
497         if (arc_extension_map.condCodes[i])
498             printf ("COND: %s\n", arc_extension_map.condCodes[i]);
499 }