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