OSDN Git Service

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