/* ARC target-dependent stuff. Extension structure access functions 
   Copyright 1995, 1997, 2000, 2001 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

#include <stdlib.h>
#include <stdio.h>
#include "bfd.h"
#include "arc-ext.h"
#include "libiberty.h"

/* Extension structure  */
static struct arcExtMap arc_extension_map;

/* Get the name of an extension instruction.  */

const char *
arcExtMap_instName(int opcode, int minor, int *flags) 
{
    if (opcode == 3) 
      {
	/* FIXME: ??? need to also check 0/1/2 in bit0 for (3f) brk/sleep/swi  */
	if (minor < 0x09 || minor == 0x3f)
	  return 0;
	else
	  opcode = 0x1f - 0x10 + minor - 0x09 + 1;
      }
    else
      if (opcode < 0x10)
	return 0;
    else
      opcode -= 0x10;
    if (!arc_extension_map.instructions[opcode])
      return 0;
    *flags = arc_extension_map.instructions[opcode]->flags;
    return arc_extension_map.instructions[opcode]->name;
}

/* Get the name of an extension core register.  */

const char *
arcExtMap_coreRegName(int value) 
{
  if (value < 32)
    return 0;
  return (const char *) arc_extension_map.coreRegisters[value-32];
}

/* Get the name of an extension condition code.  */

const char *
arcExtMap_condCodeName(int value) 
{
  if (value < 16)
    return 0;
  return (const char *) arc_extension_map.condCodes[value-16];
}

/* Get the name of an extension aux register.  */

const char *
arcExtMap_auxRegName(long address)
{
  /* walk the list of aux reg names and find the name  */
  struct ExtAuxRegister *r;

  for (r = arc_extension_map.auxRegisters; r; r = r->next) {
    if (r->address == address)
      return (const char *) r->name;
  }
  return 0;
}

/* Recursively free auxilliary register strcture pointers until
   the list is empty.  */

static void 
clean_aux_registers(struct ExtAuxRegister *r)
{
  if (r -> next)
    {
      clean_aux_registers( r->next);
      free(r -> name);
      free(r -> next);
      r ->next = NULL;
    }
  else 
    free(r -> name);
}
	      
/* Free memory that has been allocated for the extensions.  */

static void 
cleanup_ext_map(void) 
{
  struct ExtAuxRegister *r;
  struct ExtInstruction *insn;
  int i;

  /* clean aux reg structure  */
  r = arc_extension_map.auxRegisters;
  if (r) 
    {
      (clean_aux_registers(r));
      free(r);
    }
  
  /* clean instructions  */
  for (i = 0; i < NUM_EXT_INST; i++) 
    {
      insn = arc_extension_map.instructions[i];
      if (insn)
	free(insn->name);
    }
  
  /* clean core reg struct  */
  for (i = 0; i < NUM_EXT_CORE; i++) 
    {
      if (arc_extension_map.coreRegisters[i])
	free(arc_extension_map.coreRegisters[i]);
    }
  
  for (i = 0; i < NUM_EXT_COND; i++) {
    if (arc_extension_map.condCodes[i])
      free(arc_extension_map.condCodes[i]);
  }
  
  memset(&arc_extension_map, 0, sizeof(struct arcExtMap));  
}

int 
arcExtMap_add(void *base, unsigned long length) 
{
  unsigned char *block = base;
  unsigned char *p = block;
  
  /* Clean up and reset everything if needed.  */
  cleanup_ext_map();

  while (p && p < (block + length)) 
    {
      /* p[0] == length of record
	 p[1] == type of record
	 For instructions:
	   p[2]  = opcode
	   p[3]  = minor opcode (if opcode == 3)
	   p[4]  = flags
	   p[5]+ = name
	 For core regs and condition codes:
	   p[2]  = value
	   p[3]+ = name
	 For aux regs:
	   p[2..5] = value
	   p[6]+   = name
	 (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5])  */

      if (p[0] == 0)
	return -1;
      
      switch (p[1])
	{
	case EXT_INSTRUCTION:
	  {
	    char opcode = p[2];
	    char minor  = p[3];
	    char * insn_name = (char *) xmalloc(( (int)*p-5) * sizeof(char));
	    struct ExtInstruction * insn = 
	      (struct ExtInstruction *) xmalloc(sizeof(struct ExtInstruction));
	    
	    if (opcode==3)
	      opcode = 0x1f - 0x10 + minor - 0x09 + 1;
	    else
	      opcode -= 0x10;
	    insn -> flags = (char) *(p+4);
	    strcpy(insn_name, (p+5));
	    insn -> name = insn_name;
	    arc_extension_map.instructions[(int) opcode] = insn;
	  }
	  break;
	
	case EXT_CORE_REGISTER: 
	  {
	    char * core_name = (char *) xmalloc(((int)*p-3) * sizeof(char));

	    strcpy(core_name, (p+3));
	    arc_extension_map.coreRegisters[p[2]-32] = core_name;
	  }
	  break;
	  
	case EXT_COND_CODE: 
	  {
	    char * cc_name = (char *) xmalloc( ((int)*p-3) * sizeof(char));
	    strcpy(cc_name, (p+3));
	    arc_extension_map.condCodes[p[2]-16] = cc_name;
	  }	
	  break;
	  
	case EXT_AUX_REGISTER: 
	  {
	    /* trickier -- need to store linked list to these  */
	    struct ExtAuxRegister *newAuxRegister = 
	      (struct ExtAuxRegister *)malloc(sizeof(struct ExtAuxRegister));
	    char * aux_name = (char *) xmalloc ( ((int)*p-6) * sizeof(char));

	    strcpy (aux_name, (p+6));
	    newAuxRegister->name = aux_name;
	    newAuxRegister->address = p[2]<<24 | p[3]<<16 | p[4]<<8  | p[5];
	    newAuxRegister->next = arc_extension_map.auxRegisters;
	    arc_extension_map.auxRegisters = newAuxRegister;
	  }
	  break;
	  
	default:
	  return -1;
	  
	}
      p += p[0]; /* move to next record  */
    }
  
  return 0;
}

/* Load hw extension descibed in .extArcMap ELF section.  */

void
build_ARC_extmap (text_bfd)
  bfd *text_bfd;
{
  char *arcExtMap;
  bfd_size_type count;
  asection *p;

  for (p = text_bfd->sections; p != NULL; p = p->next)
    if (!strcmp (p->name, ".arcextmap"))
      {
        count = p->_raw_size;
        arcExtMap = (char *) xmalloc (count);
        if (bfd_get_section_contents (text_bfd, p, (PTR) arcExtMap, 0, count))
          {
            arcExtMap_add ((PTR) arcExtMap, count);
            break;
          }
        free ((PTR) arcExtMap);
      }
}
