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