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

   This file is part of libopcodes.

   This library 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 3, or (at your option)
   any later version.

   It 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., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, 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 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 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 = (unsigned char *) base;
  unsigned char *p = (unsigned char *) 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, (char *) (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, (char *) (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, (char *) (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, (char *) (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 = bfd_get_section_size (p);
        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);
      }
}
