source: branches/libc-0.6/src/binutils/opcodes/arc-ext.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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