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