cpu/
[deliverable/binutils-gdb.git] / opcodes / arc-ext.c
CommitLineData
5bd67f35 1/* ARC target-dependent stuff. Extension structure access functions
9b201bb5 2 Copyright 1995, 1997, 2000, 2001, 2004, 2005, 2007
53c9ebc5 3 Free Software Foundation, Inc.
0d2bcfaf 4
9b201bb5 5 This file is part of libopcodes.
0d2bcfaf 6
9b201bb5 7 This library is free software; you can redistribute it and/or modify
0d2bcfaf 8 it under the terms of the GNU General Public License as published by
9b201bb5
NC
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
0d2bcfaf 11
9b201bb5
NC
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.
0d2bcfaf
NC
16
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
9b201bb5
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
0d2bcfaf 21
5bd67f35 22#include "sysdep.h"
0d2bcfaf
NC
23#include <stdlib.h>
24#include <stdio.h>
25#include "bfd.h"
26#include "arc-ext.h"
27#include "libiberty.h"
28
29/* Extension structure */
30static struct arcExtMap arc_extension_map;
31
32/* Get the name of an extension instruction. */
33
34const char *
5bd67f35 35arcExtMap_instName(int opcode, int minor, int *flags)
0d2bcfaf 36{
5bd67f35 37 if (opcode == 3)
0d2bcfaf
NC
38 {
39 /* FIXME: ??? need to also check 0/1/2 in bit0 for (3f) brk/sleep/swi */
40 if (minor < 0x09 || minor == 0x3f)
41 return 0;
42 else
43 opcode = 0x1f - 0x10 + minor - 0x09 + 1;
44 }
45 else
46 if (opcode < 0x10)
47 return 0;
48 else
49 opcode -= 0x10;
50 if (!arc_extension_map.instructions[opcode])
51 return 0;
52 *flags = arc_extension_map.instructions[opcode]->flags;
53 return arc_extension_map.instructions[opcode]->name;
54}
55
56/* Get the name of an extension core register. */
57
58const char *
5bd67f35 59arcExtMap_coreRegName(int value)
0d2bcfaf
NC
60{
61 if (value < 32)
62 return 0;
53c9ebc5 63 return arc_extension_map.coreRegisters[value-32];
0d2bcfaf
NC
64}
65
66/* Get the name of an extension condition code. */
67
68const char *
5bd67f35 69arcExtMap_condCodeName(int value)
0d2bcfaf
NC
70{
71 if (value < 16)
72 return 0;
53c9ebc5 73 return arc_extension_map.condCodes[value-16];
0d2bcfaf
NC
74}
75
76/* Get the name of an extension aux register. */
77
78const char *
79arcExtMap_auxRegName(long address)
80{
81 /* walk the list of aux reg names and find the name */
82 struct ExtAuxRegister *r;
83
84 for (r = arc_extension_map.auxRegisters; r; r = r->next) {
85 if (r->address == address)
86 return (const char *) r->name;
87 }
88 return 0;
89}
90
91/* Recursively free auxilliary register strcture pointers until
92 the list is empty. */
93
5bd67f35 94static void
0d2bcfaf
NC
95clean_aux_registers(struct ExtAuxRegister *r)
96{
97 if (r -> next)
98 {
99 clean_aux_registers( r->next);
100 free(r -> name);
101 free(r -> next);
102 r ->next = NULL;
103 }
5bd67f35 104 else
0d2bcfaf
NC
105 free(r -> name);
106}
5bd67f35 107
0d2bcfaf
NC
108/* Free memory that has been allocated for the extensions. */
109
5bd67f35
AJ
110static void
111cleanup_ext_map(void)
0d2bcfaf
NC
112{
113 struct ExtAuxRegister *r;
114 struct ExtInstruction *insn;
115 int i;
116
117 /* clean aux reg structure */
118 r = arc_extension_map.auxRegisters;
5bd67f35 119 if (r)
0d2bcfaf
NC
120 {
121 (clean_aux_registers(r));
122 free(r);
123 }
5bd67f35 124
0d2bcfaf 125 /* clean instructions */
5bd67f35 126 for (i = 0; i < NUM_EXT_INST; i++)
0d2bcfaf
NC
127 {
128 insn = arc_extension_map.instructions[i];
129 if (insn)
130 free(insn->name);
131 }
5bd67f35 132
0d2bcfaf 133 /* clean core reg struct */
5bd67f35 134 for (i = 0; i < NUM_EXT_CORE; i++)
0d2bcfaf
NC
135 {
136 if (arc_extension_map.coreRegisters[i])
137 free(arc_extension_map.coreRegisters[i]);
138 }
5bd67f35 139
0d2bcfaf
NC
140 for (i = 0; i < NUM_EXT_COND; i++) {
141 if (arc_extension_map.condCodes[i])
142 free(arc_extension_map.condCodes[i]);
143 }
5bd67f35
AJ
144
145 memset(&arc_extension_map, 0, sizeof(struct arcExtMap));
0d2bcfaf
NC
146}
147
5bd67f35
AJ
148int
149arcExtMap_add(void *base, unsigned long length)
0d2bcfaf
NC
150{
151 unsigned char *block = base;
152 unsigned char *p = block;
5bd67f35 153
0d2bcfaf
NC
154 /* Clean up and reset everything if needed. */
155 cleanup_ext_map();
156
5bd67f35 157 while (p && p < (block + length))
0d2bcfaf
NC
158 {
159 /* p[0] == length of record
160 p[1] == type of record
161 For instructions:
162 p[2] = opcode
163 p[3] = minor opcode (if opcode == 3)
164 p[4] = flags
165 p[5]+ = name
166 For core regs and condition codes:
167 p[2] = value
168 p[3]+ = name
169 For aux regs:
170 p[2..5] = value
171 p[6]+ = name
172 (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]) */
173
174 if (p[0] == 0)
175 return -1;
5bd67f35 176
0d2bcfaf
NC
177 switch (p[1])
178 {
179 case EXT_INSTRUCTION:
180 {
181 char opcode = p[2];
182 char minor = p[3];
183 char * insn_name = (char *) xmalloc(( (int)*p-5) * sizeof(char));
5bd67f35 184 struct ExtInstruction * insn =
0d2bcfaf 185 (struct ExtInstruction *) xmalloc(sizeof(struct ExtInstruction));
5bd67f35 186
0d2bcfaf
NC
187 if (opcode==3)
188 opcode = 0x1f - 0x10 + minor - 0x09 + 1;
189 else
190 opcode -= 0x10;
191 insn -> flags = (char) *(p+4);
53c9ebc5 192 strcpy (insn_name, (char *) (p+5));
0d2bcfaf
NC
193 insn -> name = insn_name;
194 arc_extension_map.instructions[(int) opcode] = insn;
195 }
196 break;
5bd67f35
AJ
197
198 case EXT_CORE_REGISTER:
0d2bcfaf
NC
199 {
200 char * core_name = (char *) xmalloc(((int)*p-3) * sizeof(char));
201
53c9ebc5 202 strcpy(core_name, (char *) (p+3));
0d2bcfaf
NC
203 arc_extension_map.coreRegisters[p[2]-32] = core_name;
204 }
205 break;
5bd67f35
AJ
206
207 case EXT_COND_CODE:
0d2bcfaf
NC
208 {
209 char * cc_name = (char *) xmalloc( ((int)*p-3) * sizeof(char));
53c9ebc5 210 strcpy(cc_name, (char *) (p+3));
0d2bcfaf 211 arc_extension_map.condCodes[p[2]-16] = cc_name;
5bd67f35 212 }
0d2bcfaf 213 break;
5bd67f35
AJ
214
215 case EXT_AUX_REGISTER:
0d2bcfaf
NC
216 {
217 /* trickier -- need to store linked list to these */
5bd67f35 218 struct ExtAuxRegister *newAuxRegister =
0d2bcfaf
NC
219 (struct ExtAuxRegister *)malloc(sizeof(struct ExtAuxRegister));
220 char * aux_name = (char *) xmalloc ( ((int)*p-6) * sizeof(char));
221
53c9ebc5 222 strcpy (aux_name, (char *) (p+6));
0d2bcfaf
NC
223 newAuxRegister->name = aux_name;
224 newAuxRegister->address = p[2]<<24 | p[3]<<16 | p[4]<<8 | p[5];
225 newAuxRegister->next = arc_extension_map.auxRegisters;
226 arc_extension_map.auxRegisters = newAuxRegister;
227 }
228 break;
5bd67f35 229
0d2bcfaf
NC
230 default:
231 return -1;
5bd67f35 232
0d2bcfaf
NC
233 }
234 p += p[0]; /* move to next record */
235 }
5bd67f35 236
0d2bcfaf
NC
237 return 0;
238}
239
240/* Load hw extension descibed in .extArcMap ELF section. */
241
242void
243build_ARC_extmap (text_bfd)
244 bfd *text_bfd;
245{
246 char *arcExtMap;
247 bfd_size_type count;
248 asection *p;
249
250 for (p = text_bfd->sections; p != NULL; p = p->next)
251 if (!strcmp (p->name, ".arcextmap"))
252 {
52886d70 253 count = bfd_get_section_size (p);
0d2bcfaf
NC
254 arcExtMap = (char *) xmalloc (count);
255 if (bfd_get_section_contents (text_bfd, p, (PTR) arcExtMap, 0, count))
256 {
257 arcExtMap_add ((PTR) arcExtMap, count);
258 break;
259 }
260 free ((PTR) arcExtMap);
261 }
262}
This page took 0.416999 seconds and 4 git commands to generate.