]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/arc-ext.c
Copyright update for binutils
[thirdparty/binutils-gdb.git] / opcodes / arc-ext.c
CommitLineData
886a2506 1/* ARC target-dependent stuff. Extension structure access functions
6f2750fe 2 Copyright (C) 1995-2016 Free Software Foundation, Inc.
0d2bcfaf 3
9b201bb5 4 This file is part of libopcodes.
0d2bcfaf 5
9b201bb5 6 This library is free software; you can redistribute it and/or modify
0d2bcfaf 7 it under the terms of the GNU General Public License as published by
9b201bb5
NC
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
0d2bcfaf 10
9b201bb5
NC
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.
0d2bcfaf
NC
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
9b201bb5
NC
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
0d2bcfaf 20
5bd67f35 21#include "sysdep.h"
0d2bcfaf
NC
22#include <stdlib.h>
23#include <stdio.h>
886a2506 24
0d2bcfaf
NC
25#include "bfd.h"
26#include "arc-ext.h"
886a2506 27#include "elf/arc.h"
0d2bcfaf
NC
28#include "libiberty.h"
29
0d2bcfaf 30
886a2506
NC
31/* This module provides support for extensions to the ARC processor
32 architecture. */
0d2bcfaf 33
0d2bcfaf 34
886a2506 35/* Local constants. */
0d2bcfaf 36
886a2506
NC
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
0d2bcfaf 41
886a2506
NC
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)
0d2bcfaf 49
0d2bcfaf 50
886a2506 51/* Local types. */
0d2bcfaf 52
886a2506 53/* These types define the information stored in the table. */
0d2bcfaf 54
886a2506
NC
55struct ExtInstruction
56{
57 char major;
58 char minor;
59 char flags;
60 char* name;
61 struct ExtInstruction* next;
62};
63
64struct ExtAuxRegister
65{
66 long address;
67 char* name;
68 struct ExtAuxRegister* next;
69};
0d2bcfaf 70
886a2506
NC
71struct ExtCoreRegister
72{
73 short number;
74 enum ExtReadWrite rw;
75 char* name;
76};
0d2bcfaf 77
886a2506 78struct arcExtMap
0d2bcfaf 79{
886a2506
NC
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};
5bd67f35 85
0d2bcfaf 86
886a2506 87/* Local data. */
0d2bcfaf 88
886a2506
NC
89/* Extension table. */
90static struct arcExtMap arc_extension_map;
5bd67f35 91
5bd67f35 92
886a2506 93/* Local macros. */
5bd67f35 94
886a2506
NC
95/* A hash function used to map instructions into the table. */
96#define INST_HASH(MAJOR, MINOR) ((((MAJOR) << 3) ^ (MINOR)) & INST_HASH_MASK)
5bd67f35 97
0d2bcfaf 98
886a2506 99/* Local functions. */
5bd67f35 100
886a2506
NC
101static void
102create_map (unsigned char *block,
103 unsigned long length)
104{
105 unsigned char *p = block;
0d2bcfaf 106
5bd67f35 107 while (p && p < (block + length))
0d2bcfaf
NC
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
886a2506 119 For auxiliary regs:
0d2bcfaf
NC
120 p[2..5] = value
121 p[6]+ = name
886a2506 122 (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]). */
0d2bcfaf 123
886a2506
NC
124 /* The sequence of records is temrinated by an "empty"
125 record. */
0d2bcfaf 126 if (p[0] == 0)
886a2506 127 break;
5bd67f35 128
0d2bcfaf
NC
129 switch (p[1])
130 {
131 case EXT_INSTRUCTION:
132 {
886a2506
NC
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;
0d2bcfaf 146 }
5bd67f35
AJ
147
148 case EXT_CORE_REGISTER:
0d2bcfaf 149 {
886a2506
NC
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 }
0d2bcfaf 164
886a2506
NC
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);
0d2bcfaf 180 }
5bd67f35
AJ
181
182 case EXT_COND_CODE:
0d2bcfaf 183 {
886a2506
NC
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;
5bd67f35 190 }
5bd67f35
AJ
191
192 case EXT_AUX_REGISTER:
0d2bcfaf 193 {
886a2506
NC
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));
0d2bcfaf 198
0d2bcfaf 199 newAuxRegister->name = aux_name;
886a2506
NC
200 newAuxRegister->address = (p[2] << 24) | (p[3] << 16)
201 | (p[4] << 8) | p[5];
0d2bcfaf
NC
202 newAuxRegister->next = arc_extension_map.auxRegisters;
203 arc_extension_map.auxRegisters = newAuxRegister;
886a2506 204 break;
0d2bcfaf 205 }
5bd67f35 206
0d2bcfaf 207 default:
886a2506
NC
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
218static void
219destroy_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 }
5bd67f35 258
886a2506
NC
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
270static const char *
271ExtReadWrite_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
288const char *
289arcExtMap_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;
0d2bcfaf 372 }
886a2506 373 temp = temp->next;
0d2bcfaf 374 }
5bd67f35 375
886a2506 376 return NULL;
0d2bcfaf
NC
377}
378
886a2506 379/* Get the name of an extension core register. */
0d2bcfaf 380
886a2506
NC
381const char *
382arcExtMap_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
393enum ExtReadWrite
394arcExtMap_coreReadWrite (int regnum)
0d2bcfaf 395{
886a2506
NC
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
405const char *
406arcExtMap_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
417const char *
418arcExtMap_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. */
0d2bcfaf 433
886a2506
NC
434void
435build_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"))
0d2bcfaf 449 {
886a2506
NC
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 }
0d2bcfaf
NC
459 }
460}
886a2506
NC
461
462
463void
464dump_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}