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)
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. */
28 #include "libiberty.h"
31 /* extension structure */
32 static struct arcExtMap arc_extension_map
;
34 /* Get the name of an extension instruction. */
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. */
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;
71 minor
= (c
== 0x07) ? b
: c
;
73 /* 32-bit instructions. */
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);
97 minor
= (I
>> 1) | ((I
& 0x1) << 5);
100 minor
= (I
>> 1) | (I
& 0x1) | ((I
& 0x2) << 4);
115 else /* ARCTangent extension instructions. */
118 temp
= arc_extension_map
.instructions
[INST_HASH (opcode
, minor
)];
121 if ((temp
->major
== opcode
) && (temp
->minor
== minor
))
123 *flags
= temp
->flags
;
132 /* get the name of an extension core register */
134 arcExtMap_coreRegName (int value
)
138 return arc_extension_map
.coreRegisters
[value
-32].name
;
142 arcExtMap_coreReadWrite (int value
)
146 return arc_extension_map
.coreRegisters
[value
-32].rw
;
150 struct ExtAuxRegister
*
151 arc_ExtMap_auxRegs ()
153 return arc_extension_map
.auxRegisters
;
157 /* Get the name of an extension condition code. */
159 arcExtMap_condCodeName (int value
)
163 return arc_extension_map
.condCodes
[value
-16];
166 /* Get the name of an extension aux register. */
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
;
183 /* Recursively free auxilliary register strcture pointers until
184 the list is empty. */
186 clean_aux_registers (struct ExtAuxRegister
*r
)
190 clean_aux_registers (r
->next
);
199 /* Free memory that has been allocated for the extensions. */
202 cleanup_ext_map (void)
204 struct ExtAuxRegister
*r
;
205 struct ExtInstruction
*insn
;
208 /* Clean aux reg structure. */
209 r
= arc_extension_map
.auxRegisters
;
212 (clean_aux_registers (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
)
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
));
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
254 p[3] = minor opcode (if opcode == 3)
257 For core regs and condition codes:
263 (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]) */
269 case EXT_INSTRUCTION
:
271 char *insn_name
= xstrdup ((char *) (p
+5));
272 struct ExtInstruction
*insn
= XNEW (struct ExtInstruction
);
275 struct ExtInstruction
**bucket
276 = &arc_extension_map
.instructions
[INST_HASH (major
, minor
)];
278 insn
->name
= insn_name
;
282 insn
->next
= *bucket
;
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
);
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
);
308 char *cc_name
= xstrdup ((char *) (p
+3));
310 arc_extension_map
.condCodes
[p
[2]-16] = cc_name
;
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
;
329 p
+= p
[0]; /* move to next record */
334 /* Load extensions described in .arcextmap and .gnu.linkonce.arcextmap.* ELF
337 build_ARC_extmap (bfd
*text_bfd
)
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
);