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