]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/arc-ext.c
Copyright update for binutils
[thirdparty/binutils-gdb.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 }