/* Register support routines for the remote server for GDB.
   Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008
   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 3 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, see <http://www.gnu.org/licenses/>.  */

#include "server.h"
#include "regdef.h"

#include <stdlib.h>
#include <string.h>

/* The private data for the register cache.  Note that we have one
   per inferior; this is primarily for simplicity, as the performance
   benefit is minimal.  */

struct inferior_regcache_data
{
  int registers_valid;
  unsigned char *registers;
};

static int register_bytes;

static struct reg *reg_defs;
static int num_registers;

const char **gdbserver_expedite_regs;

static struct inferior_regcache_data *
get_regcache (struct thread_info *inf, int fetch)
{
  struct inferior_regcache_data *regcache;

  regcache = (struct inferior_regcache_data *) inferior_regcache_data (inf);

  if (regcache == NULL)
    fatal ("no register cache");

  /* FIXME - fetch registers for INF */
  if (fetch && regcache->registers_valid == 0)
    {
      fetch_inferior_registers (0);
      regcache->registers_valid = 1;
    }

  return regcache;
}

void
regcache_invalidate_one (struct inferior_list_entry *entry)
{
  struct thread_info *thread = (struct thread_info *) entry;
  struct inferior_regcache_data *regcache;

  regcache = (struct inferior_regcache_data *) inferior_regcache_data (thread);

  if (regcache->registers_valid)
    {
      struct thread_info *saved_inferior = current_inferior;

      current_inferior = thread;
      store_inferior_registers (-1);
      current_inferior = saved_inferior;
    }

  regcache->registers_valid = 0;
}

void
regcache_invalidate ()
{
  for_each_inferior (&all_threads, regcache_invalidate_one);
}

void *
new_register_cache (void)
{
  struct inferior_regcache_data *regcache;

  if (register_bytes == 0)
    return NULL; /* The architecture hasn't been initialized yet.  */

  regcache = xmalloc (sizeof (*regcache));

  /* Make sure to zero-initialize the register cache when it is created,
     in case there are registers the target never fetches.  This way they'll
     read as zero instead of garbage.  */
  regcache->registers = xcalloc (1, register_bytes);
  if (regcache->registers == NULL)
    fatal ("Could not allocate register cache.");

  regcache->registers_valid = 0;

  return regcache;
}

void
free_register_cache (void *regcache_p)
{
  struct inferior_regcache_data *regcache
    = (struct inferior_regcache_data *) regcache_p;

  if (regcache)
    {
      free (regcache->registers);
      free (regcache);
    }
}

static void
realloc_register_cache (struct inferior_list_entry *thread_p)
{
  struct thread_info *thread = (struct thread_info *) thread_p;

  free_register_cache (inferior_regcache_data (thread));
  set_inferior_regcache_data (thread, new_register_cache ());
}

void
set_register_cache (struct reg *regs, int n)
{
  int offset, i;
  
  reg_defs = regs;
  num_registers = n;

  offset = 0;
  for (i = 0; i < n; i++)
    {
      regs[i].offset = offset;
      offset += regs[i].size;
    }

  register_bytes = offset / 8;

  /* Make sure PBUFSIZ is large enough to hold a full register packet.  */
  if (2 * register_bytes + 32 > PBUFSIZ)
    fatal ("Register packet size exceeds PBUFSIZ.");

  /* Re-allocate all pre-existing register caches.  */
  for_each_inferior (&all_threads, realloc_register_cache);
}

void
registers_to_string (char *buf)
{
  unsigned char *registers = get_regcache (current_inferior, 1)->registers;

  convert_int_to_ascii (registers, buf, register_bytes);
}

void
registers_from_string (char *buf)
{
  int len = strlen (buf);
  unsigned char *registers = get_regcache (current_inferior, 1)->registers;

  if (len != register_bytes * 2)
    {
      warning ("Wrong sized register packet (expected %d bytes, got %d)", 2*register_bytes, len);
      if (len > register_bytes * 2)
	len = register_bytes * 2;
    }
  convert_ascii_to_int (buf, registers, len / 2);
}

struct reg *
find_register_by_name (const char *name)
{
  int i;

  for (i = 0; i < num_registers; i++)
    if (!strcmp (name, reg_defs[i].name))
      return &reg_defs[i];
  fatal ("Unknown register %s requested", name);
  return 0;
}

int
find_regno (const char *name)
{
  int i;

  for (i = 0; i < num_registers; i++)
    if (!strcmp (name, reg_defs[i].name))
      return i;
  fatal ("Unknown register %s requested", name);
  return -1;
}

struct reg *
find_register_by_number (int n)
{
  return &reg_defs[n];
}

int
register_size (int n)
{
  return reg_defs[n].size / 8;
}

static unsigned char *
register_data (int n, int fetch)
{
  unsigned char *registers
    = get_regcache (current_inferior, fetch)->registers;

  return registers + (reg_defs[n].offset / 8);
}

void
supply_register (int n, const void *buf)
{
  memcpy (register_data (n, 0), buf, register_size (n));
}

void
supply_register_by_name (const char *name, const void *buf)
{
  supply_register (find_regno (name), buf);
}

void
collect_register (int n, void *buf)
{
  memcpy (buf, register_data (n, 1), register_size (n));
}

void
collect_register_as_string (int n, char *buf)
{
  convert_int_to_ascii (register_data (n, 1), buf, register_size (n));
}

void
collect_register_by_name (const char *name, void *buf)
{
  collect_register (find_regno (name), buf);
}
