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