Back to index

cell-binutils  2.17cvs20070401
arc-ext.c
Go to the documentation of this file.
00001 /* ARC target-dependent stuff. Extension structure access functions
00002    Copyright 1995, 1997, 2000, 2001, 2004, 2005
00003    Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #include "sysdep.h"
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include "bfd.h"
00025 #include "arc-ext.h"
00026 #include "libiberty.h"
00027 
00028 /* Extension structure  */
00029 static struct arcExtMap arc_extension_map;
00030 
00031 /* Get the name of an extension instruction.  */
00032 
00033 const char *
00034 arcExtMap_instName(int opcode, int minor, int *flags)
00035 {
00036     if (opcode == 3)
00037       {
00038        /* FIXME: ??? need to also check 0/1/2 in bit0 for (3f) brk/sleep/swi  */
00039        if (minor < 0x09 || minor == 0x3f)
00040          return 0;
00041        else
00042          opcode = 0x1f - 0x10 + minor - 0x09 + 1;
00043       }
00044     else
00045       if (opcode < 0x10)
00046        return 0;
00047     else
00048       opcode -= 0x10;
00049     if (!arc_extension_map.instructions[opcode])
00050       return 0;
00051     *flags = arc_extension_map.instructions[opcode]->flags;
00052     return arc_extension_map.instructions[opcode]->name;
00053 }
00054 
00055 /* Get the name of an extension core register.  */
00056 
00057 const char *
00058 arcExtMap_coreRegName(int value)
00059 {
00060   if (value < 32)
00061     return 0;
00062   return arc_extension_map.coreRegisters[value-32];
00063 }
00064 
00065 /* Get the name of an extension condition code.  */
00066 
00067 const char *
00068 arcExtMap_condCodeName(int value)
00069 {
00070   if (value < 16)
00071     return 0;
00072   return arc_extension_map.condCodes[value-16];
00073 }
00074 
00075 /* Get the name of an extension aux register.  */
00076 
00077 const char *
00078 arcExtMap_auxRegName(long address)
00079 {
00080   /* walk the list of aux reg names and find the name  */
00081   struct ExtAuxRegister *r;
00082 
00083   for (r = arc_extension_map.auxRegisters; r; r = r->next) {
00084     if (r->address == address)
00085       return (const char *) r->name;
00086   }
00087   return 0;
00088 }
00089 
00090 /* Recursively free auxilliary register strcture pointers until
00091    the list is empty.  */
00092 
00093 static void
00094 clean_aux_registers(struct ExtAuxRegister *r)
00095 {
00096   if (r -> next)
00097     {
00098       clean_aux_registers( r->next);
00099       free(r -> name);
00100       free(r -> next);
00101       r ->next = NULL;
00102     }
00103   else
00104     free(r -> name);
00105 }
00106 
00107 /* Free memory that has been allocated for the extensions.  */
00108 
00109 static void
00110 cleanup_ext_map(void)
00111 {
00112   struct ExtAuxRegister *r;
00113   struct ExtInstruction *insn;
00114   int i;
00115 
00116   /* clean aux reg structure  */
00117   r = arc_extension_map.auxRegisters;
00118   if (r)
00119     {
00120       (clean_aux_registers(r));
00121       free(r);
00122     }
00123 
00124   /* clean instructions  */
00125   for (i = 0; i < NUM_EXT_INST; i++)
00126     {
00127       insn = arc_extension_map.instructions[i];
00128       if (insn)
00129        free(insn->name);
00130     }
00131 
00132   /* clean core reg struct  */
00133   for (i = 0; i < NUM_EXT_CORE; i++)
00134     {
00135       if (arc_extension_map.coreRegisters[i])
00136        free(arc_extension_map.coreRegisters[i]);
00137     }
00138 
00139   for (i = 0; i < NUM_EXT_COND; i++) {
00140     if (arc_extension_map.condCodes[i])
00141       free(arc_extension_map.condCodes[i]);
00142   }
00143 
00144   memset(&arc_extension_map, 0, sizeof(struct arcExtMap));
00145 }
00146 
00147 int
00148 arcExtMap_add(void *base, unsigned long length)
00149 {
00150   unsigned char *block = base;
00151   unsigned char *p = block;
00152 
00153   /* Clean up and reset everything if needed.  */
00154   cleanup_ext_map();
00155 
00156   while (p && p < (block + length))
00157     {
00158       /* p[0] == length of record
00159         p[1] == type of record
00160         For instructions:
00161           p[2]  = opcode
00162           p[3]  = minor opcode (if opcode == 3)
00163           p[4]  = flags
00164           p[5]+ = name
00165         For core regs and condition codes:
00166           p[2]  = value
00167           p[3]+ = name
00168         For aux regs:
00169           p[2..5] = value
00170           p[6]+   = name
00171         (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5])  */
00172 
00173       if (p[0] == 0)
00174        return -1;
00175 
00176       switch (p[1])
00177        {
00178        case EXT_INSTRUCTION:
00179          {
00180            char opcode = p[2];
00181            char minor  = p[3];
00182            char * insn_name = (char *) xmalloc(( (int)*p-5) * sizeof(char));
00183            struct ExtInstruction * insn =
00184              (struct ExtInstruction *) xmalloc(sizeof(struct ExtInstruction));
00185 
00186            if (opcode==3)
00187              opcode = 0x1f - 0x10 + minor - 0x09 + 1;
00188            else
00189              opcode -= 0x10;
00190            insn -> flags = (char) *(p+4);
00191            strcpy (insn_name, (char *) (p+5));
00192            insn -> name = insn_name;
00193            arc_extension_map.instructions[(int) opcode] = insn;
00194          }
00195          break;
00196 
00197        case EXT_CORE_REGISTER:
00198          {
00199            char * core_name = (char *) xmalloc(((int)*p-3) * sizeof(char));
00200 
00201            strcpy(core_name, (char *) (p+3));
00202            arc_extension_map.coreRegisters[p[2]-32] = core_name;
00203          }
00204          break;
00205 
00206        case EXT_COND_CODE:
00207          {
00208            char * cc_name = (char *) xmalloc( ((int)*p-3) * sizeof(char));
00209            strcpy(cc_name, (char *) (p+3));
00210            arc_extension_map.condCodes[p[2]-16] = cc_name;
00211          }
00212          break;
00213 
00214        case EXT_AUX_REGISTER:
00215          {
00216            /* trickier -- need to store linked list to these  */
00217            struct ExtAuxRegister *newAuxRegister =
00218              (struct ExtAuxRegister *)malloc(sizeof(struct ExtAuxRegister));
00219            char * aux_name = (char *) xmalloc ( ((int)*p-6) * sizeof(char));
00220 
00221            strcpy (aux_name, (char *) (p+6));
00222            newAuxRegister->name = aux_name;
00223            newAuxRegister->address = p[2]<<24 | p[3]<<16 | p[4]<<8  | p[5];
00224            newAuxRegister->next = arc_extension_map.auxRegisters;
00225            arc_extension_map.auxRegisters = newAuxRegister;
00226          }
00227          break;
00228 
00229        default:
00230          return -1;
00231 
00232        }
00233       p += p[0]; /* move to next record  */
00234     }
00235 
00236   return 0;
00237 }
00238 
00239 /* Load hw extension descibed in .extArcMap ELF section.  */
00240 
00241 void
00242 build_ARC_extmap (text_bfd)
00243   bfd *text_bfd;
00244 {
00245   char *arcExtMap;
00246   bfd_size_type count;
00247   asection *p;
00248 
00249   for (p = text_bfd->sections; p != NULL; p = p->next)
00250     if (!strcmp (p->name, ".arcextmap"))
00251       {
00252         count = bfd_get_section_size (p);
00253         arcExtMap = (char *) xmalloc (count);
00254         if (bfd_get_section_contents (text_bfd, p, (PTR) arcExtMap, 0, count))
00255           {
00256             arcExtMap_add ((PTR) arcExtMap, count);
00257             break;
00258           }
00259         free ((PTR) arcExtMap);
00260       }
00261 }