1185377Ssam/* ARC target-dependent stuff. Extension structure access functions 2187831Ssam Copyright 1995, 1997, 2000, 2001, 2004, 2005 3185377Ssam Free Software Foundation, Inc. 4185377Ssam 5185377Ssam This file is part of GDB. 6185377Ssam 7185377Ssam This program is free software; you can redistribute it and/or modify 8185377Ssam it under the terms of the GNU General Public License as published by 9185377Ssam the Free Software Foundation; either version 2 of the License, or 10185377Ssam (at your option) any later version. 11185377Ssam 12185377Ssam This program is distributed in the hope that it will be useful, 13185377Ssam but WITHOUT ANY WARRANTY; without even the implied warranty of 14185377Ssam MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15185377Ssam GNU General Public License for more details. 16185377Ssam 17186020Ssam You should have received a copy of the GNU General Public License 18185377Ssam along with this program; if not, write to the Free Software 19185377Ssam Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 20185377Ssam 21185377Ssam#include "sysdep.h" 22185377Ssam#include <stdlib.h> 23185377Ssam#include <stdio.h> 24185377Ssam#include "bfd.h" 25185377Ssam#include "arc-ext.h" 26185377Ssam#include "libiberty.h" 27185377Ssam 28185377Ssam/* Extension structure */ 29185377Ssamstatic struct arcExtMap arc_extension_map; 30187831Ssam 31220442Sadrian/* Get the name of an extension instruction. */ 32187831Ssam 33185377Ssamconst char * 34185377SsamarcExtMap_instName(int opcode, int minor, int *flags) 35185377Ssam{ 36185377Ssam if (opcode == 3) 37185377Ssam { 38185377Ssam /* FIXME: ??? need to also check 0/1/2 in bit0 for (3f) brk/sleep/swi */ 39185377Ssam if (minor < 0x09 || minor == 0x3f) 40185377Ssam return 0; 41185377Ssam else 42185377Ssam opcode = 0x1f - 0x10 + minor - 0x09 + 1; 43185377Ssam } 44185377Ssam else 45185377Ssam if (opcode < 0x10) 46185377Ssam return 0; 47185377Ssam else 48185377Ssam opcode -= 0x10; 49185377Ssam if (!arc_extension_map.instructions[opcode]) 50185377Ssam return 0; 51185377Ssam *flags = arc_extension_map.instructions[opcode]->flags; 52185377Ssam return arc_extension_map.instructions[opcode]->name; 53188771Ssam} 54188771Ssam 55188771Ssam/* Get the name of an extension core register. */ 56188771Ssam 57188771Ssamconst char * 58185377SsamarcExtMap_coreRegName(int value) 59185377Ssam{ 60185380Ssam if (value < 32) 61185380Ssam return 0; 62185380Ssam return arc_extension_map.coreRegisters[value-32]; 63185377Ssam} 64185377Ssam 65185377Ssam/* Get the name of an extension condition code. */ 66185377Ssam 67185377Ssamconst char * 68185377SsamarcExtMap_condCodeName(int value) 69185377Ssam{ 70185377Ssam if (value < 16) 71185377Ssam return 0; 72185377Ssam return arc_extension_map.condCodes[value-16]; 73185377Ssam} 74185377Ssam 75185377Ssam/* Get the name of an extension aux register. */ 76185377Ssam 77185406Ssamconst char * 78185406SsamarcExtMap_auxRegName(long address) 79185406Ssam{ 80185406Ssam /* walk the list of aux reg names and find the name */ 81185418Ssam struct ExtAuxRegister *r; 82185406Ssam 83185406Ssam for (r = arc_extension_map.auxRegisters; r; r = r->next) { 84217624Sadrian if (r->address == address) 85217624Sadrian return (const char *) r->name; 86185406Ssam } 87185406Ssam return 0; 88185418Ssam} 89188504Ssam 90185418Ssam/* Recursively free auxilliary register strcture pointers until 91185406Ssam the list is empty. */ 92185406Ssam 93185406Ssamstatic void 94188500Ssamclean_aux_registers(struct ExtAuxRegister *r) 95185406Ssam{ 96185377Ssam if (r -> next) 97185377Ssam { 98185406Ssam clean_aux_registers( r->next); 99185406Ssam free(r -> name); 100185406Ssam free(r -> next); 101185406Ssam r ->next = NULL; 102185406Ssam } 103185418Ssam else 104185406Ssam free(r -> name); 105185406Ssam} 106185406Ssam 107185406Ssam/* Free memory that has been allocated for the extensions. */ 108185418Ssam 109186020Ssamstatic void 110186020Ssamcleanup_ext_map(void) 111185406Ssam{ 112185406Ssam struct ExtAuxRegister *r; 113185406Ssam struct ExtInstruction *insn; 114186020Ssam int i; 115185406Ssam 116185406Ssam /* clean aux reg structure */ 117185406Ssam r = arc_extension_map.auxRegisters; 118185406Ssam if (r) 119185406Ssam { 120187831Ssam (clean_aux_registers(r)); 121187831Ssam free(r); 122187831Ssam } 123187831Ssam 124187831Ssam /* clean instructions */ 125185377Ssam for (i = 0; i < NUM_EXT_INST; i++) 126187831Ssam { 127187831Ssam insn = arc_extension_map.instructions[i]; 128187831Ssam if (insn) 129187831Ssam free(insn->name); 130187831Ssam } 131187831Ssam 132187831Ssam /* clean core reg struct */ 133187831Ssam for (i = 0; i < NUM_EXT_CORE; i++) 134185377Ssam { 135187831Ssam if (arc_extension_map.coreRegisters[i]) 136185377Ssam free(arc_extension_map.coreRegisters[i]); 137187831Ssam } 138187831Ssam 139187831Ssam for (i = 0; i < NUM_EXT_COND; i++) { 140220442Sadrian if (arc_extension_map.condCodes[i]) 141187831Ssam free(arc_extension_map.condCodes[i]); 142185377Ssam } 143185377Ssam 144185377Ssam memset(&arc_extension_map, 0, sizeof(struct arcExtMap)); 145185377Ssam} 146220442Sadrian 147220444Sadrianint 148220444SadrianarcExtMap_add(void *base, unsigned long length) 149220442Sadrian{ 150187831Ssam unsigned char *block = base; 151185377Ssam unsigned char *p = block; 152185377Ssam 153187831Ssam /* Clean up and reset everything if needed. */ 154187831Ssam cleanup_ext_map(); 155187831Ssam 156187831Ssam while (p && p < (block + length)) 157187831Ssam { 158187831Ssam /* p[0] == length of record 159187831Ssam p[1] == type of record 160187831Ssam For instructions: 161187831Ssam p[2] = opcode 162187831Ssam p[3] = minor opcode (if opcode == 3) 163185377Ssam p[4] = flags 164185377Ssam p[5]+ = name 165185377Ssam For core regs and condition codes: 166185377Ssam p[2] = value 167185377Ssam p[3]+ = name 168185377Ssam For aux regs: 169185377Ssam p[2..5] = value 170185377Ssam p[6]+ = name 171185377Ssam (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]) */ 172185377Ssam 173185377Ssam if (p[0] == 0) 174185377Ssam return -1; 175185377Ssam 176185377Ssam switch (p[1]) 177185377Ssam { 178185377Ssam case EXT_INSTRUCTION: 179185377Ssam { 180185377Ssam char opcode = p[2]; 181185377Ssam char minor = p[3]; 182185377Ssam char * insn_name = (char *) xmalloc(( (int)*p-5) * sizeof(char)); 183185377Ssam struct ExtInstruction * insn = 184185377Ssam (struct ExtInstruction *) xmalloc(sizeof(struct ExtInstruction)); 185185377Ssam 186185377Ssam if (opcode==3) 187221603Sadrian opcode = 0x1f - 0x10 + minor - 0x09 + 1; 188185377Ssam else 189185377Ssam opcode -= 0x10; 190185377Ssam insn -> flags = (char) *(p+4); 191185377Ssam strcpy (insn_name, (char *) (p+5)); 192185377Ssam insn -> name = insn_name; 193185377Ssam arc_extension_map.instructions[(int) opcode] = insn; 194185377Ssam } 195185377Ssam break; 196185377Ssam 197185377Ssam case EXT_CORE_REGISTER: 198185377Ssam { 199185377Ssam char * core_name = (char *) xmalloc(((int)*p-3) * sizeof(char)); 200185377Ssam 201221603Sadrian strcpy(core_name, (char *) (p+3)); 202185377Ssam arc_extension_map.coreRegisters[p[2]-32] = core_name; 203222584Sadrian } 204185377Ssam break; 205185377Ssam 206222584Sadrian case EXT_COND_CODE: 207195114Ssam { 208218436Sadrian char * cc_name = (char *) xmalloc( ((int)*p-3) * sizeof(char)); 209220034Sadrian strcpy(cc_name, (char *) (p+3)); 210221667Sadrian arc_extension_map.condCodes[p[2]-16] = cc_name; 211225444Sadrian } 212225444Sadrian break; 213185377Ssam 214185377Ssam case EXT_AUX_REGISTER: 215185377Ssam { 216185377Ssam /* trickier -- need to store linked list to these */ 217185377Ssam struct ExtAuxRegister *newAuxRegister = 218185377Ssam (struct ExtAuxRegister *)malloc(sizeof(struct ExtAuxRegister)); 219185377Ssam char * aux_name = (char *) xmalloc ( ((int)*p-6) * sizeof(char)); 220185377Ssam 221185377Ssam strcpy (aux_name, (char *) (p+6)); 222185377Ssam newAuxRegister->name = aux_name; 223185377Ssam newAuxRegister->address = p[2]<<24 | p[3]<<16 | p[4]<<8 | p[5]; 224185377Ssam newAuxRegister->next = arc_extension_map.auxRegisters; 225192396Ssam arc_extension_map.auxRegisters = newAuxRegister; 226218150Sadrian } 227218150Sadrian break; 228185377Ssam 229185377Ssam default: 230187831Ssam return -1; 231187831Ssam 232185377Ssam } 233185377Ssam p += p[0]; /* move to next record */ 234185380Ssam } 235185380Ssam 236185380Ssam return 0; 237185380Ssam} 238185380Ssam 239185380Ssam/* Load hw extension descibed in .extArcMap ELF section. */ 240185380Ssam 241185380Ssamvoid 242185380Ssambuild_ARC_extmap (text_bfd) 243185380Ssam bfd *text_bfd; 244185380Ssam{ 245185380Ssam char *arcExtMap; 246185380Ssam bfd_size_type count; 247185380Ssam asection *p; 248185380Ssam 249185380Ssam for (p = text_bfd->sections; p != NULL; p = p->next) 250185380Ssam if (!strcmp (p->name, ".arcextmap")) 251185377Ssam { 252185377Ssam count = bfd_get_section_size (p); 253185377Ssam arcExtMap = (char *) xmalloc (count); 254185377Ssam if (bfd_get_section_contents (text_bfd, p, (PTR) arcExtMap, 0, count)) 255185377Ssam { 256185377Ssam arcExtMap_add ((PTR) arcExtMap, count); 257185377Ssam break; 258185377Ssam } 259185377Ssam free ((PTR) arcExtMap); 260185377Ssam } 261185377Ssam} 262185377Ssam