/* 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 "sysdep.h"
#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);
      }
}
