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