Check in ARCompact simulator. A valid configuration is arc-elf.
[binutils/xnox.git] / opcodes / arc-ext.c
blobd2d838e2534b22fa24e74b8cbcfea46b1d086af8
1 /* ARC target-dependent stuff. Extension structure access functions
2 Copyright 1995, 1997, 2000, 2001, 2004, 2005, 2007
3 Free Software Foundation, Inc.
5 This file is part of libopcodes.
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include "bfd.h"
25 #include "arc-ext.h"
26 #include "elf/arc.h"
28 #include "libiberty.h"
29 #include "sysdep.h"
31 /* extension structure */
32 static struct arcExtMap arc_extension_map;
34 /* Get the name of an extension instruction. */
36 const char *
37 arcExtMap_instName (int opcode, int insn, int *flags)
39 /* Here the following tasks need to be done. First of all, the opcode
40 stored in the Extension Map is the real opcode. However, the subopcode
41 stored in the instruction to be disassembled is mangled. We pass (in
42 minor opcode), the instruction word. Here we will un-mangle it and get
43 the real subopcode which we can look for in the Extension Map. This
44 function is used both for the ARCTangent and the ARCompact, so we would
45 also need some sort of a way to distinguish between the two
46 architectures. This is because the ARCTangent does not do any of this
47 mangling so we have no issues there. */
49 /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI. If it is 1 then use
50 iiiiIi. Now, if P is 3 then check M[5:5] and if it is 0 then un-mangle
51 using iiiiiI else iiiiii. */
53 unsigned char minor;
54 struct ExtInstruction *temp;
56 if (*flags != E_ARC_MACH_A4) /* ARCompact extension instructions. */
58 /* 16-bit instructions. */
59 if (0x08 <= opcode && opcode <= 0x0b)
61 unsigned char I, b, c, i;
63 I = (insn & 0xf800) >> 11;
64 b = (insn & 0x0700) >> 8;
65 c = (insn & 0x00e0) >> 5;
66 i = (insn & 0x001f);
68 if (i)
69 minor = i;
70 else
71 minor = (c == 0x07) ? b : c;
73 /* 32-bit instructions. */
74 else
76 unsigned char P, M, I, A, B;
78 P = (insn & 0x00c00000) >> 22;
79 M = (insn & 0x00000020);
80 I = (insn & 0x003f0000) >> 16;
81 A = (insn & 0x0000003f);
82 B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
84 if (I != 0x2f)
86 #ifndef UNMANGLED
87 switch (P)
89 case 3:
90 if (M)
92 minor = I;
93 break;
95 case 0:
96 case 2:
97 minor = (I >> 1) | ((I & 0x1) << 5);
98 break;
99 case 1:
100 minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4);
102 #else
103 minor = I;
104 #endif
106 else
108 if (A != 0x3f)
109 minor = A;
110 else
111 minor = B;
115 else /* ARCTangent extension instructions. */
116 minor = insn;
118 temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
119 while (temp)
121 if ((temp->major == opcode) && (temp->minor == minor))
123 *flags = temp->flags;
124 return temp->name;
126 temp = temp->next;
129 return NULL;
132 /* get the name of an extension core register */
133 const char *
134 arcExtMap_coreRegName (int value)
136 if (value < 32)
137 return 0;
138 return arc_extension_map.coreRegisters[value-32].name;
141 enum ExtReadWrite
142 arcExtMap_coreReadWrite (int value)
144 if (value < 32)
145 return REG_INVALID;
146 return arc_extension_map.coreRegisters[value-32].rw;
149 #if 0
150 struct ExtAuxRegister *
151 arc_ExtMap_auxRegs ()
153 return arc_extension_map.auxRegisters;
155 #endif
157 /* Get the name of an extension condition code. */
158 const char *
159 arcExtMap_condCodeName (int value)
161 if (value < 16)
162 return 0;
163 return arc_extension_map.condCodes[value-16];
166 /* Get the name of an extension aux register. */
168 const char *
169 arcExtMap_auxRegName (long address)
171 /* Walk the list of aux reg names and find the name. */
172 struct ExtAuxRegister *r;
174 for (r = arc_extension_map.auxRegisters; r; r = r->next)
176 if (r->address == address)
177 return (const char *)r->name;
179 return 0;
182 #if 0
183 /* Recursively free auxilliary register strcture pointers until
184 the list is empty. */
185 static void
186 clean_aux_registers (struct ExtAuxRegister *r)
188 if (r -> next)
190 clean_aux_registers (r->next);
191 free (r->name);
192 free (r->next);
193 r->next = NULL;
195 else
196 free (r->name);
199 /* Free memory that has been allocated for the extensions. */
201 static void
202 cleanup_ext_map (void)
204 struct ExtAuxRegister *r;
205 struct ExtInstruction *insn;
206 int i;
208 /* Clean aux reg structure. */
209 r = arc_extension_map.auxRegisters;
210 if (r)
212 (clean_aux_registers (r));
213 free (r);
216 /* Clean instructions. */
217 for (i = INST_HASH_SIZE - 1; i >= 0; i--)
219 for (insn = arc_extension_map.instructions[i]; insn ; insn = insn->next)
221 free (insn->name);
222 free (insn);
226 /* Clean core reg struct. */
227 for (i = 0; i < NUM_EXT_CORE; i++)
229 if (arc_extension_map.coreRegisters[i].name)
230 free (arc_extension_map.coreRegisters[i].name);
233 for (i = 0; i < NUM_EXT_COND; i++) {
234 if (arc_extension_map.condCodes[i])
235 free (arc_extension_map.condCodes[i]);
238 memset (&arc_extension_map, 0, sizeof (struct arcExtMap));
240 #endif
243 arcExtMap_add (void *base, unsigned long length)
245 unsigned char *block = base;
246 unsigned char *p = block;
248 while (p && p < (block + length))
250 /* p[0] == length of record
251 p[1] == type of record
252 For instructions:
253 p[2] = opcode
254 p[3] = minor opcode (if opcode == 3)
255 p[4] = flags
256 p[5]+ = name
257 For core regs and condition codes:
258 p[2] = value
259 p[3]+ = name
260 For aux regs:
261 p[2..5] = value
262 p[6]+ = name
263 (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]) */
264 if (p[0] == 0)
265 return -1;
267 switch (p[1])
268 { /* type */
269 case EXT_INSTRUCTION:
271 char *insn_name = xstrdup ((char *) (p+5));
272 struct ExtInstruction *insn = XNEW (struct ExtInstruction);
273 int major = p[2];
274 int minor = p[3];
275 struct ExtInstruction **bucket
276 = &arc_extension_map.instructions[INST_HASH (major, minor)];
278 insn->name = insn_name;
279 insn->major = major;
280 insn->minor = minor;
281 insn->flags = p[4];
282 insn->next = *bucket;
283 *bucket = insn;
284 break;
286 case EXT_CORE_REGISTER:
288 unsigned char number = p[2];
289 char *name = (char *) p+3;
291 arc_extension_map.coreRegisters[number-32].number = number;
292 arc_extension_map.coreRegisters[number-32].rw = REG_READWRITE;
293 arc_extension_map.coreRegisters[number-32].name = xstrdup (name);
294 break;
296 case EXT_LONG_CORE_REGISTER:
298 unsigned char number = p[2];
299 char *name = (char *) p+7;
300 enum ExtReadWrite rw = p[6];
302 arc_extension_map.coreRegisters[number-32].number = number;
303 arc_extension_map.coreRegisters[number-32].rw = rw;
304 arc_extension_map.coreRegisters[number-32].name = xstrdup (name);
306 case EXT_COND_CODE:
308 char *cc_name = xstrdup ((char *) (p+3));
310 arc_extension_map.condCodes[p[2]-16] = cc_name;
311 break;
313 case EXT_AUX_REGISTER:
315 /* trickier -- need to store linked list to these */
316 struct ExtAuxRegister *newAuxRegister
317 = XNEW (struct ExtAuxRegister);
318 char *aux_name = xstrdup ((char *) (p+6));
320 newAuxRegister->name = aux_name;
321 newAuxRegister->address = p[2]<<24 | p[3]<<16 | p[4]<<8 | p[5];
322 newAuxRegister->next = arc_extension_map.auxRegisters;
323 arc_extension_map.auxRegisters = newAuxRegister;
324 break;
326 default:
327 return -1;
329 p += p[0]; /* move to next record */
331 return 0;
334 /* Load extensions described in .arcextmap and .gnu.linkonce.arcextmap.* ELF
335 section. */
336 void
337 build_ARC_extmap (bfd *text_bfd)
339 char *arcExtMap;
340 bfd_size_type count;
341 asection *p;
343 for (p = text_bfd->sections; p != NULL; p = p->next)
344 if (!strncmp (p->name,
345 ".gnu.linkonce.arcextmap.",
346 sizeof (".gnu.linkonce.arcextmap.")-1)
347 || !strcmp (p->name,".arcextmap"))
349 count = bfd_get_section_size (p);
350 arcExtMap = (char *) xmalloc (count);
351 if (bfd_get_section_contents (text_bfd, p, (PTR) arcExtMap, 0, count))
352 arcExtMap_add ((PTR) arcExtMap, count);
353 free ((PTR) arcExtMap);