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 */ 28 static struct arcExtMap arc_extension_map; 29 30 /* Get the name of an extension instruction. */ 31 32 const char * 33 arcExtMap_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 56 const char * 57 arcExtMap_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 66 const char * 67 arcExtMap_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 76 const char * 77 arcExtMap_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 92 static void 93 clean_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 108 static void 109 cleanup_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 146 int 147 arcExtMap_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 240 void 241 build_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 } 261