1 /* ARC target-dependent stuff. Extension structure access functions
2 Copyright (C) 1995-2016 Free Software Foundation, Inc.
4 This file is part of libopcodes.
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)
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.
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. */
28 #include "libiberty.h"
31 /* This module provides support for extensions to the ARC processor
35 /* Local constants. */
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
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)
53 /* These types define the information stored in the table. */
61 struct ExtInstruction* next;
68 struct ExtAuxRegister* next;
71 struct ExtCoreRegister
80 struct ExtAuxRegister* auxRegisters;
81 struct ExtInstruction* instructions[INST_HASH_SIZE];
82 struct ExtCoreRegister coreRegisters[NUM_EXT_CORE];
83 char* condCodes[NUM_EXT_COND];
89 /* Extension table. */
90 static struct arcExtMap arc_extension_map;
95 /* A hash function used to map instructions into the table. */
96 #define INST_HASH(MAJOR, MINOR) ((((MAJOR) << 3) ^ (MINOR)) & INST_HASH_MASK)
99 /* Local functions. */
102 create_map (unsigned char *block,
103 unsigned long length)
105 unsigned char *p = block;
107 while (p && p < (block + length))
109 /* p[0] == length of record
110 p[1] == type of record
113 p[3] = minor opcode (if opcode == 3)
116 For core regs and condition codes:
122 (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]). */
124 /* The sequence of records is temrinated by an "empty"
131 case EXT_INSTRUCTION:
133 struct ExtInstruction *insn = XNEW (struct ExtInstruction);
136 struct ExtInstruction **bucket =
137 &arc_extension_map.instructions[INST_HASH (major, minor)];
139 insn->name = xstrdup ((char *) (p + 5));
143 insn->next = *bucket;
148 case EXT_CORE_REGISTER:
150 unsigned char number = p[2];
151 char* name = (char *) (p + 3);
154 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
157 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
160 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
165 case EXT_LONG_CORE_REGISTER:
167 unsigned char number = p[2];
168 char* name = (char *) (p + 7);
169 enum ExtReadWrite rw = p[6];
172 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
175 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
178 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
184 char *cc_name = xstrdup ((char *) (p + 3));
187 condCodes[p[2] - FIRST_EXTENSION_CONDITION_CODE]
192 case EXT_AUX_REGISTER:
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));
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;
211 p += p[0]; /* Move on to next record. */
216 /* Free memory that has been allocated for the extensions. */
221 struct ExtAuxRegister *r;
224 /* Free auxiliary registers. */
225 r = arc_extension_map.auxRegisters;
228 /* N.B. after r has been freed, r->next is invalid! */
229 struct ExtAuxRegister* next = r->next;
236 /* Free instructions. */
237 for (i = 0; i < INST_HASH_SIZE; i++)
239 struct ExtInstruction *insn = arc_extension_map.instructions[i];
243 /* N.B. after insn has been freed, insn->next is invalid! */
244 struct ExtInstruction *next = insn->next;
252 /* Free core registers. */
253 for (i = 0; i < NUM_EXT_CORE; i++)
255 if (arc_extension_map.coreRegisters[i].name)
256 free (arc_extension_map.coreRegisters[i].name);
259 /* Free condition codes. */
260 for (i = 0; i < NUM_EXT_COND; i++)
262 if (arc_extension_map.condCodes[i])
263 free (arc_extension_map.condCodes[i]);
266 memset (&arc_extension_map, 0, sizeof (arc_extension_map));
271 ExtReadWrite_image (enum ExtReadWrite val)
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 "???";
284 /* Externally visible functions. */
286 /* Get the name of an extension instruction. */
289 arcExtMap_instName (int opcode,
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. */
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. */
309 struct ExtInstruction *temp;
311 /* 16-bit instructions. */
312 if (0x08 <= opcode && opcode <= 0x0b)
314 unsigned char b, c, i;
316 b = (insn & 0x0700) >> 8;
317 c = (insn & 0x00e0) >> 5;
323 minor = (c == 0x07) ? b : c;
325 /* 32-bit instructions. */
328 unsigned char I, A, B;
330 I = (insn & 0x003f0000) >> 16;
331 A = (insn & 0x0000003f);
332 B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
347 minor = (I >> 1) | ((I & 0x1) << 5);
350 minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4);
365 temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
368 if ((temp->major == opcode) && (temp->minor == minor))
370 *flags = temp->flags;
379 /* Get the name of an extension core register. */
382 arcExtMap_coreRegName (int regnum)
384 if (regnum < FIRST_EXTENSION_CORE_REGISTER
385 || regnum > LAST_EXTENSION_CONDITION_CODE)
387 return arc_extension_map.
388 coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name;
391 /* Get the access mode of an extension core register. */
394 arcExtMap_coreReadWrite (int regnum)
396 if (regnum < FIRST_EXTENSION_CORE_REGISTER
397 || regnum > LAST_EXTENSION_CONDITION_CODE)
399 return arc_extension_map.
400 coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw;
403 /* Get the name of an extension condition code. */
406 arcExtMap_condCodeName (int code)
408 if (code < FIRST_EXTENSION_CONDITION_CODE
409 || code > LAST_EXTENSION_CONDITION_CODE)
411 return arc_extension_map.
412 condCodes[code - FIRST_EXTENSION_CONDITION_CODE];
415 /* Get the name of an extension auxiliary register. */
418 arcExtMap_auxRegName (long address)
420 /* Walk the list of auxiliary register names and find the name. */
421 struct ExtAuxRegister *r;
423 for (r = arc_extension_map.auxRegisters; r; r = r->next)
425 if (r->address == address)
426 return (const char *)r->name;
431 /* Load extensions described in .arcextmap and
432 .gnu.linkonce.arcextmap.* ELF section. */
435 build_ARC_extmap (bfd *text_bfd)
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
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"))
450 bfd_size_type count = bfd_get_section_size (sect);
451 unsigned char* buffer = xmalloc (count);
455 if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count))
456 create_map (buffer, count);
464 dump_ARC_extmap (void)
466 struct ExtAuxRegister *r;
469 r = arc_extension_map.auxRegisters;
473 printf ("AUX : %s %ld\n", r->name, r->address);
477 for (i = 0; i < INST_HASH_SIZE; i++)
479 struct ExtInstruction *insn;
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);
487 for (i = 0; i < NUM_EXT_CORE; i++)
489 struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
492 printf ("CORE: %s %d %s\n", reg.name, reg.number,
493 ExtReadWrite_image (reg.rw));
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]);